Added P R zero.dotted.
This commit is contained in:
parent
075cd395d1
commit
b38408bb9b
515
font.patel
515
font.patel
|
@ -1,14 +1,15 @@
|
|||
define font [require './empty.json']
|
||||
define bezierCubic2Q2 [require 'node-sfnt/lib/math/bezierCubic2Q2']
|
||||
define glyphList font.glyf
|
||||
define glyphs (.'.notdef' glyphList.0)
|
||||
define Bezier [require 'bezier-js']
|
||||
define Smooth [require './smooth.js'].Smooth
|
||||
define intersection [require './intersection.js'].intersection
|
||||
|
||||
|
||||
define Glyph [require './support/glyph'].Glyph
|
||||
define Stroke [require './support/stroke'].Stroke
|
||||
|
||||
define para (
|
||||
.width 500
|
||||
.stroke 85
|
||||
.dotsize 100
|
||||
.sb 50
|
||||
.cap 771
|
||||
.xheight 572
|
||||
|
@ -17,230 +18,46 @@ define para (
|
|||
.smallsmooth 242
|
||||
.o [-8]
|
||||
.descender [-178]
|
||||
.kappa 0.51
|
||||
)
|
||||
|
||||
define TINY 0.0001
|
||||
define LITTLE 0.01
|
||||
define variantSelector (
|
||||
.zero 'slashed'
|
||||
)
|
||||
|
||||
# metrics
|
||||
define DESCENDER para.descender
|
||||
define O para.o
|
||||
define WIDTH para.width
|
||||
define STROKE para.stroke
|
||||
define HALFSTROKE : STROKE / 2
|
||||
define SB para.sb
|
||||
define CAP para.cap
|
||||
define XH para.xheight
|
||||
define XO : XH - O
|
||||
define O para.o
|
||||
define SB para.sb
|
||||
define HOOK para.hook
|
||||
define SMOOTH para.smooth
|
||||
define SMALLSMOOTH para.smallsmooth
|
||||
define STROKE para.stroke
|
||||
define DOTSIZE para.dotsize
|
||||
|
||||
|
||||
# derived metrics
|
||||
define XO : XH - O
|
||||
define CAPO : CAP - O
|
||||
define HALFSTROKE : STROKE / 2
|
||||
define RIGHTSB : WIDTH - SB
|
||||
define CAP_SMOOTH : CAP - SMOOTH
|
||||
define MIDDLE : WIDTH / 2
|
||||
define KAPPA 0.51
|
||||
define CAPMIDDLE : CAP / 2
|
||||
define CAP_SMOOTH : CAP - SMOOTH
|
||||
define DOTRADIUS : para.dotsize / 2
|
||||
|
||||
# style parameters
|
||||
define KAPPA para.kappa
|
||||
define COKAPPA : 1 - KAPPA
|
||||
define COBKAPPA : COKAPPA - 0.1
|
||||
define BKAPPA : KAPPA + 0.1
|
||||
define CAPMIDDLE : CAP / 2
|
||||
define CAPO : CAP - O
|
||||
define ESS : STROKE * 0.5
|
||||
define SAMPLES 4
|
||||
define KAPPA_HOOK 0.7
|
||||
|
||||
define [Glyph name] : begin {
|
||||
set this.name name
|
||||
set this.unicode ()
|
||||
set this.contours ()
|
||||
set this.advanceWidth 500
|
||||
return nothing
|
||||
}
|
||||
define [Glyph.prototype.set-width w] : begin {
|
||||
this.advanceWidth = w
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.assign-unicode u] : begin {
|
||||
this.unicode.push [u.charCodeAt 0]
|
||||
return this
|
||||
}
|
||||
|
||||
define [Glyph.prototype.start-from x y] : begin {
|
||||
this.contours.push ((.x x .y y .onCurve true))
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.line-to x y] : begin {
|
||||
this.contours`[this.contours.length - 1].push (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.curve-to xc yc x y] : begin {
|
||||
this.contours`[this.contours.length - 1].push (.x xc .y yc .onCurve false) (.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 {
|
||||
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] [begin {
|
||||
local p2 contour`[j + 1]
|
||||
this.curve-to point.x point.y p2.x p2.y
|
||||
j = j + 1
|
||||
}]]
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
define [Stroke] : begin {
|
||||
this.points = ()
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.set-width d1 d2] : begin {
|
||||
local point this.points`[this.points.length - 1]
|
||||
point.d1 = d1
|
||||
point.d2 = d2
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.start-from x y] : begin {
|
||||
this.points = ((.x x .y y .onCurve true))
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.line-to x y] : begin {
|
||||
this.points.push (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.curve-to xc yc x y] : begin {
|
||||
this.points.push (.x xc .y yc .onCurve false) (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.cubic-to x1 y1 x2 y2 x y] : begin {
|
||||
this.points.push (.x x1 .y y1 .onCurve false .cubic true) (.x x2 .y y2 .onCurve false .cubic true) (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.arc-vh-to x y] : begin {
|
||||
local last this.points`[this.points.length - 1]
|
||||
this.cubic-to last.x [last.y + BKAPPA * [y - last.y]] [x + BKAPPA * [last.x - x]] y x y
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.arc-hv-to x y] : begin {
|
||||
local last this.points`[this.points.length - 1]
|
||||
this.cubic-to [last.x + BKAPPA * [x - last.x]] last.y x [y + BKAPPA * [last.y - y]] x y
|
||||
return this
|
||||
}
|
||||
define [dforward p0 p1 p2 p3] (
|
||||
.x [p0.x + [[-11] / 6 * p0.x + 3 * p1.x - 3 / 2 * p2.x + p3.x / 3] / TINY * LITTLE]
|
||||
.y [p0.y + [[-11] / 6 * p0.y + 3 * p1.y - 3 / 2 * p2.y + p3.y / 3] / TINY * LITTLE]
|
||||
)
|
||||
define [dbackward p0 p1 p2 p3] (
|
||||
.x [p0.x + [11 / 6 * p0.x - 3 * p1.x + 3 / 2 * p2.x - p3.x / 3] / TINY * LITTLE]
|
||||
.y [p0.y + [11 / 6 * p0.y - 3 * p1.y + 3 / 2 * p2.y - p3.y / 3] / TINY * LITTLE]
|
||||
)
|
||||
define [nonlinear a b c] : [Math.abs [[c.y - a.y] * [b.x - a.x] - [c.x - a.x] * [b.y - a.y]]] > TINY
|
||||
|
||||
define [Stroke.prototype.form-stroke d1 d2] : begin {
|
||||
local d1s ([set d1 [if [this.points.0.d1 >= 0] this.points.0.d1 d1]])
|
||||
local d2s ([set d2 [if [this.points.0.d2 >= 0] this.points.0.d2 d2]])
|
||||
local subSegments ()
|
||||
local p0 this.points.0
|
||||
for [local j 1] [j < this.points.length] [inc j] : begin {
|
||||
local p1 this.points`j
|
||||
piecewise {
|
||||
p1.onCurve : begin {
|
||||
subSegments.push (p0 (.x [[p0.x + p1.x] / 2] .y [[p0.y + p1.y] / 2]) p1)
|
||||
d1s.push : set d1 [if [p1.d1 >= 0] p1.d1 d1]
|
||||
d2s.push : set d2 [if [p1.d2 >= 0] p1.d2 d2]
|
||||
p0 = p1
|
||||
}
|
||||
p1.cubic : begin {
|
||||
local p2 this.points`[j + 1]
|
||||
local p3 this.points`[j + 2]
|
||||
d1s.push : set d1 [if [p3.d1 >= 0] p3.d1 d1]
|
||||
d2s.push : set d2 [if [p3.d2 >= 0] p3.d2 d2]
|
||||
subSegments.push (p0 p1 p2 p3)
|
||||
p0 = p3
|
||||
j = j + 2
|
||||
}
|
||||
true : begin {
|
||||
local p2 this.points`[j + 1]
|
||||
d1s.push : set d1 [if [p2.d1 >= 0] p2.d1 d1]
|
||||
d2s.push : set d2 [if [p2.d2 >= 0] p2.d2 d2]
|
||||
subSegments.push (p0 p1 p2)
|
||||
p0 = p2
|
||||
j = j + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
local f1 : Smooth d1s (.method 'cubic')
|
||||
local f2 : Smooth d2s (.method 'cubic')
|
||||
local left ()
|
||||
local right ()
|
||||
for [local j 0] [j < subSegments.length] [inc j] : begin {
|
||||
local seg subSegments`j
|
||||
local curve : if [seg.length > 3] [new Bezier seg.0.x seg.0.y seg.1.x seg.1.y seg.2.x seg.2.y seg.3.x seg.3.y] [new Bezier seg.0.x seg.0.y seg.1.x seg.1.y seg.2.x seg.2.y]
|
||||
foreach sample [range 0 SAMPLES] : begin {
|
||||
local t : j + sample / SAMPLES
|
||||
local tn : j + [sample + 1] / SAMPLES
|
||||
|
||||
local lthis : curve.offset [sample / SAMPLES] [f1 t]
|
||||
local rthis : curve.offset [sample / SAMPLES] [-[f2 t]]
|
||||
|
||||
local lnext : curve.offset [[sample + 1] / SAMPLES] [f1 tn]
|
||||
local rnext : curve.offset [[sample + 1] / SAMPLES] [-[f2 tn]]
|
||||
|
||||
local lnthis1 : curve.offset [sample / SAMPLES + TINY] [f1 [t + TINY]]
|
||||
local rnthis1 : curve.offset [sample / SAMPLES + TINY] [-[f2 [t + TINY]]]
|
||||
local lnnext1 : curve.offset [[sample + 1] / SAMPLES - TINY] [f1 [tn - TINY]]
|
||||
local rnnext1 : curve.offset [[sample + 1] / SAMPLES - TINY] [-[f2 [tn - TINY]]]
|
||||
local lnthis2 : curve.offset [sample / SAMPLES + [TINY * 2]] [f1 [t + [TINY * 2]]]
|
||||
local rnthis2 : curve.offset [sample / SAMPLES + [TINY * 2]] [-[f2 [t + [TINY * 2]]]]
|
||||
local lnnext2 : curve.offset [[sample + 1] / SAMPLES - [TINY * 2]] [f1 [tn - [TINY * 2]]]
|
||||
local rnnext2 : curve.offset [[sample + 1] / SAMPLES - [TINY * 2]] [-[f2 [tn - [TINY * 2]]]]
|
||||
local lnthis3 : curve.offset [sample / SAMPLES + [TINY * 3]] [f1 [t + [TINY * 3]]]
|
||||
local rnthis3 : curve.offset [sample / SAMPLES + [TINY * 3]] [-[f2 [t + [TINY * 3]]]]
|
||||
local lnnext3 : curve.offset [[sample + 1] / SAMPLES - [TINY * 3]] [f1 [tn - [TINY * 3]]]
|
||||
local rnnext3 : curve.offset [[sample + 1] / SAMPLES - [TINY * 3]] [-[f2 [tn - [TINY * 3]]]]
|
||||
|
||||
local dlthis [dforward lthis lnthis1 lnthis2 lnthis3]
|
||||
local drthis [dforward rthis rnthis1 rnthis2 rnthis3]
|
||||
local dlnext [dbackward lnext lnnext1 lnnext2 lnnext3]
|
||||
local drnext [dbackward rnext rnnext2 rnnext2 rnnext3]
|
||||
|
||||
local il : intersection lthis.x lthis.y dlthis.x dlthis.y lnext.x lnext.y dlnext.x dlnext.y
|
||||
local ir : intersection rthis.x rthis.y drthis.x drthis.y rnext.x rnext.y drnext.x drnext.y
|
||||
|
||||
if [[il.x != null] && [il.y != null] && [nonlinear lthis il lnext]] [then {
|
||||
left.push (.x lthis.x .y lthis.y .onCurve true) (.x il.x .y il.y .onCurve false)
|
||||
}] [else {
|
||||
left.push (.x lthis.x .y lthis.y .onCurve true)
|
||||
}]
|
||||
|
||||
if [[ir.x != null] && [ir.y != null] && [nonlinear rthis ir rnext]] [then {
|
||||
right.push (.x rthis.x .y rthis.y .onCurve true) (.x ir.x .y ir.y .onCurve false)
|
||||
}] [else {
|
||||
right.push (.x rthis.x .y rthis.y .onCurve true)
|
||||
}]
|
||||
}
|
||||
}
|
||||
left.push [begin [local last [curve.offset 1 [f1 t]]] (.x last.x .y last.y .onCurve true)]
|
||||
right.push [begin [local last [curve.offset 1 [-[f2 t]]]] (.x last.x .y last.y .onCurve true)]
|
||||
|
||||
local shape : left.concat [right.reverse] :.map [[p] -> (.x p.x .y p.y .onCurve p.onCurve)]
|
||||
return (shape)
|
||||
}
|
||||
Stroke.bindParameters para
|
||||
|
||||
define [Ring u d l r] : begin {
|
||||
local my [[u + d] / 2]
|
||||
|
@ -278,6 +95,7 @@ define-macro glyph-construction : syntax-rules {
|
|||
local cubic-to : this.cubic-to.bind this
|
||||
local put-shapes : this.put-shapes.bind this
|
||||
local reverse-last : this.reverse-last.bind this
|
||||
local include-glyph : this.include-glyph.bind this
|
||||
begin @::[steps.map formOf]
|
||||
return nothing
|
||||
}]] env)
|
||||
|
@ -306,6 +124,7 @@ create-glyph 'bar' : glyph-construction {
|
|||
:.form-stroke
|
||||
}
|
||||
|
||||
### A X Y : Capital letters with curly stands
|
||||
create-glyph 'A' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'A'
|
||||
|
@ -380,24 +199,8 @@ create-glyph 'Y' : glyph-construction {
|
|||
put-shapes bartwo
|
||||
put-shapes : new Stroke :.start-from MIDDLE 0 :.set-width HALFSTROKE HALFSTROKE :.line-to MIDDLE [cross + HALFSTROKE] :.form-stroke
|
||||
}
|
||||
create-glyph 'x' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'x'
|
||||
|
||||
local TURN [XH * 0.1]
|
||||
|
||||
local barone : new Stroke
|
||||
:.start-from [SB + HALFSTROKE] 0
|
||||
:.set-width HALFSTROKE HALFSTROKE
|
||||
:.cubic-to [SB + HALFSTROKE] [TURN + 0.17 * [XH - TURN]] [RIGHTSB - HALFSTROKE] [XH - TURN - 0.17 * [XH - TURN]] [RIGHTSB - HALFSTROKE] XH
|
||||
:.form-stroke
|
||||
|
||||
local bartwo : list : barone.0.map [[pt] -> (.x [WIDTH - pt.x] .y pt.y .onCurve pt.onCurve .cubic pt.cubic)] :.reverse
|
||||
|
||||
put-shapes barone
|
||||
put-shapes bartwo
|
||||
}
|
||||
|
||||
### B D P R
|
||||
create-glyph 'B' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'B'
|
||||
|
@ -430,19 +233,6 @@ create-glyph 'B' : glyph-construction {
|
|||
put-shapes : leftbar.form-stroke 0 STROKE
|
||||
}
|
||||
|
||||
create-glyph 'C' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'C'
|
||||
local outline : new Stroke
|
||||
outline.start-from [RIGHTSB - SB * 0.1] [CAP - HOOK]
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - para.sb]] CAPO MIDDLE CAPO
|
||||
:.cubic-to [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] CAPO SB [CAP - COBKAPPA * SMOOTH] SB CAP_SMOOTH
|
||||
:.line-to SB SMOOTH
|
||||
:.cubic-to SB [COBKAPPA * SMOOTH] [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] O [WIDTH / 2] O
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - SB]] O [RIGHTSB - SB * 0.1] HOOK
|
||||
put-shapes : outline.form-stroke STROKE 0
|
||||
}
|
||||
|
||||
create-glyph 'D' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'D'
|
||||
|
@ -464,6 +254,56 @@ create-glyph 'D' : glyph-construction {
|
|||
put-shapes : bowl.form-stroke STROKE 0
|
||||
put-shapes : leftbar.form-stroke 0 STROKE
|
||||
}
|
||||
create-glyph 'P' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'P'
|
||||
|
||||
local bowl CAPMIDDLE
|
||||
local bkappa [COKAPPA - 0.2]
|
||||
|
||||
local turntop : [CAP + [bowl - HALFSTROKE]] / 2
|
||||
local turnbottom : bowl / 2
|
||||
|
||||
local topbowl : new Stroke
|
||||
topbowl.start-from SB CAP
|
||||
:.line-to [RIGHTSB - turnbottom] CAP
|
||||
:.cubic-to [RIGHTSB - bkappa * turnbottom] CAP RIGHTSB [turntop + [CAP - turntop] * KAPPA] RIGHTSB turntop
|
||||
:.cubic-to RIGHTSB [turntop + KAPPA * [bowl - HALFSTROKE - turntop]] [RIGHTSB - bkappa * turnbottom] [bowl - HALFSTROKE] [RIGHTSB - turnbottom] [bowl - HALFSTROKE]
|
||||
:.line-to SB [bowl - HALFSTROKE]
|
||||
|
||||
local leftbar : new Stroke :.start-from SB 0 :.line-to SB CAP
|
||||
|
||||
put-shapes : topbowl.form-stroke 0 STROKE
|
||||
put-shapes : leftbar.form-stroke 0 STROKE
|
||||
}
|
||||
create-glyph 'R' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'R'
|
||||
include-glyph glyphs.P
|
||||
|
||||
local TURN [XH * 0.1]
|
||||
local right [RIGHTSB + O]
|
||||
put-shapes : new Stroke
|
||||
:.start-from [right - HALFSTROKE] 0
|
||||
:.set-width HALFSTROKE HALFSTROKE
|
||||
:.curve-to [right - HALFSTROKE] [TURN + 0.1 * [XH - TURN]] MIDDLE CAPMIDDLE
|
||||
:.form-stroke
|
||||
}
|
||||
|
||||
### C G O zero Q
|
||||
|
||||
create-glyph 'C' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'C'
|
||||
local outline : new Stroke
|
||||
outline.start-from [RIGHTSB - SB * 0.1] [CAP - HOOK]
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - para.sb]] CAPO MIDDLE CAPO
|
||||
:.cubic-to [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] CAPO SB [CAP - COBKAPPA * SMOOTH] SB CAP_SMOOTH
|
||||
:.line-to SB SMOOTH
|
||||
:.cubic-to SB [COBKAPPA * SMOOTH] [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] O [WIDTH / 2] O
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - SB]] O [RIGHTSB - SB * 0.1] HOOK
|
||||
put-shapes : outline.form-stroke STROKE 0
|
||||
}
|
||||
|
||||
create-glyph 'G' : glyph-construction {
|
||||
set-width WIDTH
|
||||
|
@ -495,6 +335,104 @@ create-glyph 'O' : glyph-construction {
|
|||
:.cubic-to RIGHTSB [CAP - COBKAPPA * SMOOTH] [MIDDLE + BKAPPA * [RIGHTSB - MIDDLE]] CAPO MIDDLE CAPO
|
||||
put-shapes : outline.form-stroke STROKE 0
|
||||
}
|
||||
|
||||
create-glyph 'zero.slashed' : glyph-construction {
|
||||
set-width WIDTH
|
||||
|
||||
put-shapes glyphs.O.contours
|
||||
|
||||
local bar : new Stroke :.start-from [SB + STROKE / 2] [CAP * [1 - 0.65]] :.line-to [RIGHTSB - STROKE / 2] [CAP * 0.65]
|
||||
put-shapes : bar.form-stroke [STROKE / 2] [STROKE / 2]
|
||||
}
|
||||
create-glyph 'zero.unslashed' : glyph-construction {
|
||||
include-glyph glyphs.O
|
||||
}
|
||||
create-glyph 'zero.dotted' : glyph-construction {
|
||||
include-glyph glyphs.O
|
||||
put-shapes : list {
|
||||
Ring [CAPMIDDLE + DOTRADIUS] [CAPMIDDLE - DOTRADIUS] [MIDDLE + DOTRADIUS] [MIDDLE - DOTRADIUS]
|
||||
}
|
||||
}
|
||||
create-glyph 'zero' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode '0'
|
||||
include-glyph glyphs.[match variantSelector.zero {
|
||||
'slashed' 'zero.slashed'
|
||||
'dotted' 'zero.dotted'
|
||||
'unslahsed' 'zero.unslashed'
|
||||
otherwise 'zero.slashed'
|
||||
}]
|
||||
}
|
||||
|
||||
create-glyph 'Q' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'Q'
|
||||
|
||||
put-shapes glyphs.O.contours
|
||||
start-from MIDDLE 0
|
||||
line-to [MIDDLE + STROKE / 2] [-CAP * 0.2]
|
||||
line-to [MIDDLE + STROKE / 2 + STROKE] [-CAP * 0.2]
|
||||
line-to [MIDDLE + STROKE] 0
|
||||
line-to [MIDDLE + STROKE * [1 - 0.5 / 3]] [STROKE * 0.5]
|
||||
reverse-last
|
||||
}
|
||||
|
||||
|
||||
### H L
|
||||
create-glyph 'H' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'H'
|
||||
|
||||
put-shapes : new Stroke :.start-from SB 0 :.set-width 0 STROKE :.line-to SB CAP :.form-stroke
|
||||
put-shapes : new Stroke :.start-from RIGHTSB 0 :.set-width STROKE 0 :.line-to RIGHTSB CAP :.form-stroke
|
||||
put-shapes : new Stroke :.start-from SB [CAP / 2] :.set-width HALFSTROKE HALFSTROKE :.line-to RIGHTSB [CAP / 2] :.form-stroke
|
||||
}
|
||||
|
||||
create-glyph 'L' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'L'
|
||||
|
||||
put-shapes : new Stroke :.start-from [SB * 1.5] CAP :.line-to [SB * 1.5] 0 :.line-to RIGHTSB 0 :.form-stroke STROKE 0
|
||||
}
|
||||
|
||||
|
||||
### S
|
||||
create-glyph 'S' : glyph-construction {
|
||||
set-width WIDTH; assign-unicode 'S'
|
||||
|
||||
local slope 0.11
|
||||
|
||||
local bowltop : new Stroke
|
||||
bowltop.start-from [RIGHTSB - SB * 0.1] [CAP - HOOK]
|
||||
:.set-width STROKE 0
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - para.sb]] CAPO MIDDLE CAPO
|
||||
:.cubic-to [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] CAPO SB [CAP - COBKAPPA * SMOOTH] SB CAP_SMOOTH
|
||||
|
||||
local strokemiddle : new Stroke
|
||||
strokemiddle.start-from [SB + STROKE / 2] CAP_SMOOTH
|
||||
:.set-width [STROKE / 2] [STROKE / 2]
|
||||
:.curve-to [SB + STROKE / 2] [[0.5 + slope] * CAP + [2 * slope * CAP] / [0.4 * WIDTH] * [0.3 * WIDTH - SB - STROKE / 2]] [0.3 * WIDTH] [[0.5 + slope] * CAP]
|
||||
:.line-to [0.7 * WIDTH] [[0.5 - slope] * CAP]
|
||||
:.curve-to [RIGHTSB - STROKE / 2] [[0.5 - slope] * CAP - [2 * slope * CAP] / [0.4 * WIDTH] * [0.3 * WIDTH - SB - STROKE / 2]] [RIGHTSB - STROKE / 2] SMOOTH
|
||||
|
||||
local bowlbottom : new Stroke
|
||||
bowlbottom.start-from RIGHTSB SMOOTH :.set-width 0 STROKE
|
||||
:.cubic-to RIGHTSB [COBKAPPA * SMOOTH] [MIDDLE + BKAPPA * [RIGHTSB - MIDDLE]] O MIDDLE O
|
||||
:.curve-to [MIDDLE - KAPPA_HOOK * [MIDDLE - para.sb]] O [SB * 1.1] HOOK
|
||||
|
||||
put-shapes : bowltop.form-stroke
|
||||
put-shapes : strokemiddle.form-stroke
|
||||
put-shapes : bowlbottom.form-stroke
|
||||
}
|
||||
create-glyph 'dollar' : glyph-construction {
|
||||
set-width WIDTH; assign-unicode '$'
|
||||
put-shapes glyphs.S.contours
|
||||
put-shapes : new Stroke :.start-from MIDDLE CAP :.set-width HALFSTROKE HALFSTROKE :.line-to MIDDLE [CAP - DESCENDER / 2] :.form-stroke
|
||||
put-shapes : new Stroke :.start-from MIDDLE [DESCENDER / 2] :.set-width HALFSTROKE HALFSTROKE :.line-to MIDDLE 0 :.form-stroke
|
||||
}
|
||||
|
||||
|
||||
|
||||
create-glyph 'o' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'o'
|
||||
|
@ -504,7 +442,6 @@ create-glyph 'o' : glyph-construction {
|
|||
}
|
||||
reverse-last
|
||||
}
|
||||
|
||||
create-glyph 'o.left' : glyph-construction {
|
||||
set-width WIDTH
|
||||
# build outline manually
|
||||
|
@ -541,6 +478,12 @@ create-glyph 'q' : glyph-construction {
|
|||
put-shapes glyphs.'o.right'.contours
|
||||
put-shapes : new Stroke :.start-from RIGHTSB XH :.set-width 0 STROKE :.line-to RIGHTSB DESCENDER :.form-stroke
|
||||
}
|
||||
create-glyph 'd' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'd'
|
||||
put-shapes glyphs.'o.right'.contours
|
||||
put-shapes : new Stroke :.start-from RIGHTSB 0 :.set-width STROKE 0 :.line-to RIGHTSB CAP :.form-stroke
|
||||
}
|
||||
create-glyph 'g' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'g'
|
||||
|
@ -569,82 +512,26 @@ create-glyph 'g' : glyph-construction {
|
|||
line-to MIDDLE [XH - STROKE - O]
|
||||
line-to MODDLE XH
|
||||
}
|
||||
create-glyph 'd' : glyph-construction {
|
||||
|
||||
|
||||
create-glyph 'x' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'd'
|
||||
put-shapes glyphs.'o.right'.contours
|
||||
put-shapes : new Stroke :.start-from RIGHTSB 0 :.set-width STROKE 0 :.line-to RIGHTSB CAP :.form-stroke
|
||||
assign-unicode 'x'
|
||||
|
||||
local TURN [XH * 0.1]
|
||||
|
||||
local barone : new Stroke
|
||||
:.start-from [SB + HALFSTROKE] 0
|
||||
:.set-width HALFSTROKE HALFSTROKE
|
||||
:.cubic-to [SB + HALFSTROKE] [TURN + 0.17 * [XH - TURN]] [RIGHTSB - HALFSTROKE] [XH - TURN - 0.17 * [XH - TURN]] [RIGHTSB - HALFSTROKE] XH
|
||||
:.form-stroke
|
||||
|
||||
local bartwo : list : barone.0.map [[pt] -> (.x [WIDTH - pt.x] .y pt.y .onCurve pt.onCurve .cubic pt.cubic)] :.reverse
|
||||
|
||||
put-shapes barone
|
||||
put-shapes bartwo
|
||||
}
|
||||
|
||||
create-glyph 'zero' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode '0'
|
||||
put-shapes glyphs.O.contours
|
||||
|
||||
local bar : new Stroke :.start-from [SB + STROKE / 2] [CAP * [1 - 0.65]] :.line-to [RIGHTSB - STROKE / 2] [CAP * 0.65]
|
||||
put-shapes : bar.form-stroke [STROKE / 2] [STROKE / 2]
|
||||
}
|
||||
|
||||
create-glyph 'Q' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'Q'
|
||||
|
||||
put-shapes glyphs.O.contours
|
||||
start-from MIDDLE 0
|
||||
line-to [MIDDLE + STROKE / 2] [-CAP * 0.2]
|
||||
line-to [MIDDLE + STROKE / 2 + STROKE] [-CAP * 0.2]
|
||||
line-to [MIDDLE + STROKE] 0
|
||||
line-to [MIDDLE + STROKE * [1 - 0.5 / 3]] [STROKE * 0.5]
|
||||
reverse-last
|
||||
}
|
||||
|
||||
create-glyph 'H' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'H'
|
||||
|
||||
put-shapes : new Stroke :.start-from SB 0 :.set-width 0 STROKE :.line-to SB CAP :.form-stroke
|
||||
put-shapes : new Stroke :.start-from RIGHTSB 0 :.set-width STROKE 0 :.line-to RIGHTSB CAP :.form-stroke
|
||||
put-shapes : new Stroke :.start-from SB [CAP / 2] :.set-width HALFSTROKE HALFSTROKE :.line-to RIGHTSB [CAP / 2] :.form-stroke
|
||||
}
|
||||
|
||||
create-glyph 'L' : glyph-construction {
|
||||
set-width WIDTH
|
||||
assign-unicode 'L'
|
||||
|
||||
put-shapes : new Stroke :.start-from [SB * 1.5] CAP :.line-to [SB * 1.5] 0 :.form-stroke STROKE 0
|
||||
put-shapes : new Stroke :.start-from [SB * 1.5] 0 :.line-to RIGHTSB 0 :.form-stroke STROKE 0
|
||||
}
|
||||
create-glyph 'S' : glyph-construction {
|
||||
set-width WIDTH; assign-unicode 'S'
|
||||
|
||||
local slope 0.11
|
||||
|
||||
local bowltop : new Stroke
|
||||
bowltop.start-from [RIGHTSB - SB * 0.1] [CAP - HOOK]
|
||||
:.set-width STROKE 0
|
||||
:.curve-to [MIDDLE + KAPPA_HOOK * [MIDDLE - para.sb]] CAPO MIDDLE CAPO
|
||||
:.cubic-to [SB + [1 - BKAPPA] * [WIDTH / 2 - SB]] CAPO SB [CAP - COBKAPPA * SMOOTH] SB CAP_SMOOTH
|
||||
|
||||
local strokemiddle : new Stroke
|
||||
strokemiddle.start-from [SB + STROKE / 2] CAP_SMOOTH
|
||||
:.set-width [STROKE / 2] [STROKE / 2]
|
||||
:.curve-to [SB + STROKE / 2] [[0.5 + slope] * CAP + [2 * slope * CAP] / [0.4 * WIDTH] * [0.3 * WIDTH - SB - STROKE / 2]] [0.3 * WIDTH] [[0.5 + slope] * CAP]
|
||||
:.line-to [0.7 * WIDTH] [[0.5 - slope] * CAP]
|
||||
:.curve-to [RIGHTSB - STROKE / 2] [[0.5 - slope] * CAP - [2 * slope * CAP] / [0.4 * WIDTH] * [0.3 * WIDTH - SB - STROKE / 2]] [RIGHTSB - STROKE / 2] SMOOTH
|
||||
|
||||
local bowlbottom : new Stroke
|
||||
bowlbottom.start-from RIGHTSB SMOOTH :.set-width 0 STROKE
|
||||
:.cubic-to RIGHTSB [COBKAPPA * SMOOTH] [MIDDLE + BKAPPA * [RIGHTSB - MIDDLE]] O MIDDLE O
|
||||
:.curve-to [MIDDLE - KAPPA_HOOK * [MIDDLE - para.sb]] O [SB * 1.1] HOOK
|
||||
|
||||
put-shapes : bowltop.form-stroke
|
||||
put-shapes : strokemiddle.form-stroke
|
||||
put-shapes : bowlbottom.form-stroke
|
||||
}
|
||||
create-glyph 'dollar' : glyph-construction {
|
||||
set-width WIDTH; assign-unicode '$'
|
||||
put-shapes glyphs.S.contours
|
||||
put-shapes : new Stroke :.start-from MIDDLE CAP :.set-width HALFSTROKE HALFSTROKE :.line-to MIDDLE [CAP - DESCENDER / 2] :.form-stroke
|
||||
put-shapes : new Stroke :.start-from MIDDLE [DESCENDER / 2] :.set-width HALFSTROKE HALFSTROKE :.line-to MIDDLE 0 :.form-stroke
|
||||
}
|
||||
exports.font = font
|
6
makefile
6
makefile
|
@ -1,8 +1,10 @@
|
|||
JSFILES = font.js
|
||||
JSFILES = font.js support/glyph.js support/stroke.js
|
||||
|
||||
all : $(JSFILES)
|
||||
|
||||
$(JSFILES) :
|
||||
patel-c $< -o $@
|
||||
|
||||
font.js : font.patel
|
||||
font.js : font.patel
|
||||
support/glyph.js : support/glyph.patel
|
||||
support/stroke.js : support/stroke.patel
|
129
support/glyph.js
Normal file
129
support/glyph.js
Normal file
|
@ -0,0 +1,129 @@
|
|||
{
|
||||
var r0_bezierCubic2Q2, r0_Glyph, _r0_t0, _r0_t1, _r0_t2, _r0_t3, _r0_t4, _r0_t5, _r0_t6, _r0_t7, _r0_t8, _r0_t9;
|
||||
r0_bezierCubic2Q2 = require('node-sfnt/lib/math/bezierCubic2Q2');
|
||||
r0_Glyph = function _r0_t0(r1_name) {
|
||||
var r1_name, _r1_t0;
|
||||
_r1_t0 = this;
|
||||
_r1_t0['name'] = r1_name;
|
||||
_r1_t0['unicode'] = [];
|
||||
_r1_t0['contours'] = [];
|
||||
_r1_t0['advanceWidth'] = 500;
|
||||
return void 0;
|
||||
};
|
||||
r0_Glyph['prototype']['set-width'] = function _r0_t1(r2_w) {
|
||||
var r2_w, _r2_t0;
|
||||
_r2_t0 = this;
|
||||
_r2_t0['advanceWidth'] = r2_w;
|
||||
return _r2_t0;
|
||||
};
|
||||
r0_Glyph['prototype']['assign-unicode'] = function _r0_t2(r3_u) {
|
||||
var r3_u, _r3_t0;
|
||||
_r3_t0 = this;
|
||||
_r3_t0['unicode']['push'](r3_u['charCodeAt'](0));
|
||||
return _r3_t0;
|
||||
};
|
||||
r0_Glyph['prototype']['start-from'] = function _r0_t3(r4_x, r4_y) {
|
||||
var r4_x, r4_y, _r4_t0;
|
||||
_r4_t0 = this;
|
||||
_r4_t0['contours']['push']([{
|
||||
'x': r4_x,
|
||||
'y': r4_y,
|
||||
'onCurve': true
|
||||
}]);
|
||||
return _r4_t0;
|
||||
};
|
||||
r0_Glyph['prototype']['line-to'] = function _r0_t4(r5_x, r5_y) {
|
||||
var r5_x, r5_y, _r5_t0;
|
||||
_r5_t0 = this;
|
||||
_r5_t0['contours'][_r5_t0['contours']['length'] - 1]['push']({
|
||||
'x': r5_x,
|
||||
'y': r5_y,
|
||||
'onCurve': true
|
||||
});
|
||||
return _r5_t0;
|
||||
};
|
||||
r0_Glyph['prototype']['curve-to'] = function _r0_t5(r6_xc, r6_yc, r6_x, r6_y) {
|
||||
var r6_xc, r6_yc, r6_x, r6_y, _r6_t0;
|
||||
_r6_t0 = this;
|
||||
_r6_t0['contours'][_r6_t0['contours']['length'] - 1]['push']({
|
||||
'x': r6_xc,
|
||||
'y': r6_yc,
|
||||
'onCurve': false
|
||||
}, {
|
||||
'x': r6_x,
|
||||
'y': r6_y,
|
||||
'onCurve': true
|
||||
});
|
||||
return _r6_t0;
|
||||
};
|
||||
r0_Glyph['prototype']['cubic-to'] = function _r0_t6(r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y) {
|
||||
var r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y, r7_lastContour, r7_lastPoint, r7_segments, r7_p0, r7_xc, r7_yc, r7_xf, r7_yf, _r7_t0, _r7_t1, _r7_t2, _r7_t3, _r7_t4, _r7_t5, _r7_t6;
|
||||
_r7_t6 = this;
|
||||
r7_lastContour = _r7_t6['contours'][_r7_t6['contours']['length'] - 1];
|
||||
r7_lastPoint = r7_lastContour[r7_lastContour['length'] - 1];
|
||||
r7_segments = r0_bezierCubic2Q2(r7_lastPoint, {
|
||||
'x': r7_x1,
|
||||
'y': r7_y1
|
||||
}, {
|
||||
'x': r7_x2,
|
||||
'y': r7_y2
|
||||
}, {
|
||||
'x': r7_x,
|
||||
'y': r7_y
|
||||
});
|
||||
_r7_t0 = r7_segments;
|
||||
_r7_t1 = _r7_t0['length'];
|
||||
_r7_t2 = 0;
|
||||
for (; _r7_t2 < _r7_t1; _r7_t2 = _r7_t2 + 1) {
|
||||
_r7_t3 = _r7_t0[_r7_t2];
|
||||
r7_p0 = _r7_t3[0];
|
||||
_r7_t4 = _r7_t3[1];
|
||||
r7_xc = _r7_t4['x'];
|
||||
r7_yc = _r7_t4['y'];
|
||||
_r7_t5 = _r7_t3[2];
|
||||
r7_xf = _r7_t5['x'];
|
||||
r7_yf = _r7_t5['y'];
|
||||
_r7_t6['curve-to'](r7_xc, r7_yc, r7_xf, r7_yf);
|
||||
}
|
||||
return _r7_t6;
|
||||
};
|
||||
r0_Glyph['prototype']['reverse-last'] = function _r0_t7() {
|
||||
var _r9_t0;
|
||||
_r9_t0 = this;
|
||||
return _r9_t0['contours'][_r9_t0['contours']['length'] - 1] = _r9_t0['contours'][_r9_t0['contours']['length'] - 1]['reverse']();
|
||||
};
|
||||
r0_Glyph['prototype']['put-shapes'] = function _r0_t8(r10_contours) {
|
||||
var r10_contours, r10_contour, r10_j, r10_point, r10_p2, r10_p3, _r10_t0, _r10_t1, _r10_t2, _r10_t3;
|
||||
_r10_t3 = this;
|
||||
_r10_t0 = r10_contours;
|
||||
_r10_t1 = _r10_t0['length'];
|
||||
_r10_t2 = 0;
|
||||
for (; _r10_t2 < _r10_t1; _r10_t2 = _r10_t2 + 1) {
|
||||
r10_contour = _r10_t0[_r10_t2];
|
||||
_r10_t3['start-from'](r10_contour[0]['x'], r10_contour[0]['y']);
|
||||
r10_j = 1;
|
||||
for (; r10_j < r10_contour['length']; r10_j = r10_j + 1) {
|
||||
r10_point = r10_contour[r10_j];
|
||||
if (r10_point['cubic']) {
|
||||
r10_p2 = r10_contour[r10_j + 1];
|
||||
r10_p3 = r10_contour[r10_j + 2];
|
||||
_r10_t3['cubic-to'](r10_point['x'], r10_point['y'], r10_p2['x'], r10_p2['y'], r10_p3['x'], r10_p3['y']);
|
||||
r10_j = r10_j + 2;
|
||||
} else if (r10_point['onCurve'])
|
||||
_r10_t3['line-to'](r10_point['x'], r10_point['y']);
|
||||
else {
|
||||
r10_p2 = r10_contour[r10_j + 1];
|
||||
_r10_t3['curve-to'](r10_point['x'], r10_point['y'], r10_p2['x'], r10_p2['y']);
|
||||
r10_j = r10_j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _r10_t3;
|
||||
};
|
||||
r0_Glyph['prototype']['include-glyph'] = function _r0_t9(r12_glyph) {
|
||||
var r12_glyph, _r12_t0;
|
||||
_r12_t0 = this;
|
||||
return _r12_t0['put-shapes'](r12_glyph['contours']);
|
||||
};
|
||||
exports['Glyph'] = r0_Glyph;
|
||||
}
|
61
support/glyph.patel
Normal file
61
support/glyph.patel
Normal file
|
@ -0,0 +1,61 @@
|
|||
define bezierCubic2Q2 [require 'node-sfnt/lib/math/bezierCubic2Q2']
|
||||
define [Glyph name] : begin {
|
||||
set this.name name
|
||||
set this.unicode ()
|
||||
set this.contours ()
|
||||
set this.advanceWidth 500
|
||||
return nothing
|
||||
}
|
||||
define [Glyph.prototype.set-width w] : begin {
|
||||
this.advanceWidth = w
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.assign-unicode u] : begin {
|
||||
this.unicode.push [u.charCodeAt 0]
|
||||
return this
|
||||
}
|
||||
|
||||
define [Glyph.prototype.start-from x y] : begin {
|
||||
this.contours.push ((.x x .y y .onCurve true))
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.line-to x y] : begin {
|
||||
this.contours`[this.contours.length - 1].push (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.curve-to xc yc x y] : begin {
|
||||
this.contours`[this.contours.length - 1].push (.x xc .y yc .onCurve false) (.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 {
|
||||
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] [begin {
|
||||
local p2 contour`[j + 1]
|
||||
this.curve-to point.x point.y p2.x p2.y
|
||||
j = j + 1
|
||||
}]]
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
define [Glyph.prototype.include-glyph glyph] : this.put-shapes glyph.contours
|
||||
|
||||
exports.Glyph = Glyph
|
326
support/stroke.js
Normal file
326
support/stroke.js
Normal file
|
@ -0,0 +1,326 @@
|
|||
{
|
||||
var r0_Smooth, r0_intersection, r0_Bezier, r0_SAMPLES, r0_TINY, r0_LITTLE, r0_KAPPA, r0_COKAPPA, r0_BKAPPA, r0_COBKAPPA, r0_Stroke, r0_dforward, r0_dbackward, r0_nonlinear, _r0_t0, _r0_t1, _r0_t2, _r0_t3, _r0_t4, _r0_t5, _r0_t6, _r0_t7, _r0_t8, _r0_t9, _r0_t10, _r0_t11, _r0_t12;
|
||||
r0_Smooth = require('./smooth')['Smooth'];
|
||||
r0_intersection = require('./intersection')['intersection'];
|
||||
r0_Bezier = require('bezier-js');
|
||||
r0_SAMPLES = 4;
|
||||
r0_TINY = 0.0001;
|
||||
r0_LITTLE = 0.01;
|
||||
r0_KAPPA = 0.51;
|
||||
r0_COKAPPA = 1 - r0_KAPPA;
|
||||
r0_BKAPPA = r0_KAPPA + 0.1;
|
||||
r0_COBKAPPA = r0_COKAPPA - 0.1;
|
||||
r0_Stroke = function _r0_t0() {
|
||||
var _r1_t0;
|
||||
_r1_t0 = this;
|
||||
_r1_t0['points'] = [];
|
||||
return _r1_t0;
|
||||
};
|
||||
r0_Stroke['bindParameters'] = function _r0_t1(r2_para) {
|
||||
var r2_para;
|
||||
r0_KAPPA = r2_para['kappa'];
|
||||
r0_COKAPPA = 1 - r0_KAPPA;
|
||||
r0_COBKAPPA = r0_COKAPPA - 0.1;
|
||||
return r0_BKAPPA = r0_KAPPA + 0.1;
|
||||
};
|
||||
r0_Stroke['prototype']['set-width'] = function _r0_t2(r3_d1, r3_d2) {
|
||||
var r3_d1, r3_d2, r3_point, _r3_t0;
|
||||
_r3_t0 = this;
|
||||
r3_point = _r3_t0['points'][_r3_t0['points']['length'] - 1];
|
||||
r3_point['d1'] = r3_d1;
|
||||
r3_point['d2'] = r3_d2;
|
||||
return _r3_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['start-from'] = function _r0_t3(r4_x, r4_y) {
|
||||
var r4_x, r4_y, _r4_t0;
|
||||
_r4_t0 = this;
|
||||
_r4_t0['points'] = [{
|
||||
'x': r4_x,
|
||||
'y': r4_y,
|
||||
'onCurve': true
|
||||
}];
|
||||
return _r4_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['line-to'] = function _r0_t4(r5_x, r5_y) {
|
||||
var r5_x, r5_y, _r5_t0;
|
||||
_r5_t0 = this;
|
||||
_r5_t0['points']['push']({
|
||||
'x': r5_x,
|
||||
'y': r5_y,
|
||||
'onCurve': true
|
||||
});
|
||||
return _r5_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['curve-to'] = function _r0_t5(r6_xc, r6_yc, r6_x, r6_y) {
|
||||
var r6_xc, r6_yc, r6_x, r6_y, _r6_t0;
|
||||
_r6_t0 = this;
|
||||
_r6_t0['points']['push']({
|
||||
'x': r6_xc,
|
||||
'y': r6_yc,
|
||||
'onCurve': false
|
||||
}, {
|
||||
'x': r6_x,
|
||||
'y': r6_y,
|
||||
'onCurve': true
|
||||
});
|
||||
return _r6_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['cubic-to'] = function _r0_t6(r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y) {
|
||||
var r7_x1, r7_y1, r7_x2, r7_y2, r7_x, r7_y, _r7_t0;
|
||||
_r7_t0 = this;
|
||||
_r7_t0['points']['push']({
|
||||
'x': r7_x1,
|
||||
'y': r7_y1,
|
||||
'onCurve': false,
|
||||
'cubic': true
|
||||
}, {
|
||||
'x': r7_x2,
|
||||
'y': r7_y2,
|
||||
'onCurve': false,
|
||||
'cubic': true
|
||||
}, {
|
||||
'x': r7_x,
|
||||
'y': r7_y,
|
||||
'onCurve': true
|
||||
});
|
||||
return _r7_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['arc-vh-to'] = function _r0_t7(r8_x, r8_y) {
|
||||
var r8_x, r8_y, r8_last, _r8_t0;
|
||||
_r8_t0 = this;
|
||||
r8_last = _r8_t0['points'][_r8_t0['points']['length'] - 1];
|
||||
_r8_t0['cubic-to'](r8_last['x'], r8_last['y'] + r0_BKAPPA * (r8_y - r8_last['y']), r8_x + r0_BKAPPA * (r8_last['x'] - r8_x), r8_y, r8_x, r8_y);
|
||||
return _r8_t0;
|
||||
};
|
||||
r0_Stroke['prototype']['arc-hv-to'] = function _r0_t8(r9_x, r9_y) {
|
||||
var r9_x, r9_y, r9_last, _r9_t0;
|
||||
_r9_t0 = this;
|
||||
r9_last = _r9_t0['points'][_r9_t0['points']['length'] - 1];
|
||||
_r9_t0['cubic-to'](r9_last['x'] + r0_BKAPPA * (r9_x - r9_last['x']), r9_last['y'], r9_x, r9_y + r0_BKAPPA * (r9_last['y'] - r9_y), r9_x, r9_y);
|
||||
return _r9_t0;
|
||||
};
|
||||
r0_dforward = function _r0_t9(r10_p0, r10_p1, r10_p2, r10_p3) {
|
||||
var r10_p0, r10_p1, r10_p2, r10_p3;
|
||||
return {
|
||||
'x': r10_p0['x'] + (-11 / 6 * r10_p0['x'] + 3 * r10_p1['x'] - 3 / 2 * r10_p2['x'] + r10_p3['x'] / 3) / r0_TINY * r0_LITTLE,
|
||||
'y': r10_p0['y'] + (-11 / 6 * r10_p0['y'] + 3 * r10_p1['y'] - 3 / 2 * r10_p2['y'] + r10_p3['y'] / 3) / r0_TINY * r0_LITTLE
|
||||
};
|
||||
};
|
||||
r0_dbackward = function _r0_t10(r11_p0, r11_p1, r11_p2, r11_p3) {
|
||||
var r11_p0, r11_p1, r11_p2, r11_p3;
|
||||
return {
|
||||
'x': r11_p0['x'] + (11 / 6 * r11_p0['x'] - 3 * r11_p1['x'] + 3 / 2 * r11_p2['x'] - r11_p3['x'] / 3) / r0_TINY * r0_LITTLE,
|
||||
'y': r11_p0['y'] + (11 / 6 * r11_p0['y'] - 3 * r11_p1['y'] + 3 / 2 * r11_p2['y'] - r11_p3['y'] / 3) / r0_TINY * r0_LITTLE
|
||||
};
|
||||
};
|
||||
r0_nonlinear = function _r0_t11(r12_a, r12_b, r12_c) {
|
||||
var r12_a, r12_b, r12_c;
|
||||
return Math['abs']((r12_c['y'] - r12_a['y']) * (r12_b['x'] - r12_a['x']) - (r12_c['x'] - r12_a['x']) * (r12_b['y'] - r12_a['y'])) > r0_TINY;
|
||||
};
|
||||
r0_Stroke['prototype']['form-stroke'] = function _r0_t12(r13_d1, r13_d2) {
|
||||
var r13_d1, r13_d2, r13_d1s, r13_d2s, r13_subSegments, r13_p0, r13_j, r13_p1, r13_p2, r13_p3, r13_f1, r13_f2, r13_left, r13_right, r13_seg, r13_curve, r13_sample, r13_t, r13_tn, r13_lthis, r13_rthis, r13_lnext, r13_rnext, r13_lnthis1, r13_rnthis1, r13_lnnext1, r13_rnnext1, r13_lnthis2, r13_rnthis2, r13_lnnext2, r13_rnnext2, r13_lnthis3, r13_rnthis3, r13_lnnext3, r13_rnnext3, r13_dlthis, r13_drthis, r13_dlnext, r13_drnext, r13_il, r13_ir, r13_last, r13_shape, _r13_t0, _r13_t1, _r13_t2, _r13_t3, _r13_t4, _r13_t5, _r13_t6, _r13_t7, _r13_t8, _r13_t9, _r13_t10, _r13_t11, _r13_t12, _r13_t13, _r13_t14, _r13_t15, _r13_t16, _r13_t17, _r13_t18, _r13_t19, _r13_t20, _r13_t21, _r13_t22, _r13_t23, _r13_t24, _r13_t25, _r13_t26, _r13_t27, _r13_t28, _r13_t29, _r13_t30, _r13_t31, _r13_t32, _r13_t33, _r13_t34, _r13_t35, _r13_t36, _r13_t37, _r13_t38;
|
||||
_r13_t2 = this;
|
||||
if (_r13_t2['points'][0]['d1'] >= 0)
|
||||
_r13_t3 = _r13_t2['points'][0]['d1'];
|
||||
else
|
||||
_r13_t3 = r13_d1;
|
||||
_r13_t4 = r13_d1 = _r13_t3;
|
||||
r13_d1s = [_r13_t4];
|
||||
if (_r13_t2['points'][0]['d2'] >= 0)
|
||||
_r13_t5 = _r13_t2['points'][0]['d2'];
|
||||
else
|
||||
_r13_t5 = r13_d2;
|
||||
_r13_t6 = r13_d2 = _r13_t5;
|
||||
r13_d2s = [_r13_t6];
|
||||
r13_subSegments = [];
|
||||
r13_p0 = _r13_t2['points'][0];
|
||||
r13_j = 1;
|
||||
for (; r13_j < this['points']['length']; r13_j = r13_j + 1) {
|
||||
r13_p1 = _r13_t2['points'][r13_j];
|
||||
if (r13_p1['onCurve']) {
|
||||
r13_subSegments['push']([
|
||||
r13_p0,
|
||||
{
|
||||
'x': (r13_p0['x'] + r13_p1['x']) / 2,
|
||||
'y': (r13_p0['y'] + r13_p1['y']) / 2
|
||||
},
|
||||
r13_p1
|
||||
]);
|
||||
_r13_t7 = r13_d1s;
|
||||
_r13_t8 = _r13_t7['push'];
|
||||
if (r13_p1['d1'] >= 0)
|
||||
_r13_t9 = r13_p1['d1'];
|
||||
else
|
||||
_r13_t9 = r13_d1;
|
||||
_r13_t10 = r13_d1 = _r13_t9;
|
||||
_r13_t8['call'](_r13_t7, _r13_t10);
|
||||
_r13_t11 = r13_d2s;
|
||||
_r13_t12 = _r13_t11['push'];
|
||||
if (r13_p1['d2'] >= 0)
|
||||
_r13_t13 = r13_p1['d2'];
|
||||
else
|
||||
_r13_t13 = r13_d2;
|
||||
_r13_t14 = r13_d2 = _r13_t13;
|
||||
_r13_t12['call'](_r13_t11, _r13_t14);
|
||||
r13_p0 = r13_p1;
|
||||
} else if (r13_p1['cubic']) {
|
||||
r13_p2 = _r13_t2['points'][r13_j + 1];
|
||||
r13_p3 = _r13_t2['points'][r13_j + 2];
|
||||
_r13_t15 = r13_d1s;
|
||||
_r13_t16 = _r13_t15['push'];
|
||||
if (r13_p3['d1'] >= 0)
|
||||
_r13_t17 = r13_p3['d1'];
|
||||
else
|
||||
_r13_t17 = r13_d1;
|
||||
_r13_t18 = r13_d1 = _r13_t17;
|
||||
_r13_t16['call'](_r13_t15, _r13_t18);
|
||||
_r13_t19 = r13_d2s;
|
||||
_r13_t20 = _r13_t19['push'];
|
||||
if (r13_p3['d2'] >= 0)
|
||||
_r13_t21 = r13_p3['d2'];
|
||||
else
|
||||
_r13_t21 = r13_d2;
|
||||
_r13_t22 = r13_d2 = _r13_t21;
|
||||
_r13_t20['call'](_r13_t19, _r13_t22);
|
||||
r13_subSegments['push']([
|
||||
r13_p0,
|
||||
r13_p1,
|
||||
r13_p2,
|
||||
r13_p3
|
||||
]);
|
||||
r13_p0 = r13_p3;
|
||||
r13_j = r13_j + 2;
|
||||
} else if (true) {
|
||||
r13_p2 = _r13_t2['points'][r13_j + 1];
|
||||
_r13_t23 = r13_d1s;
|
||||
_r13_t24 = _r13_t23['push'];
|
||||
if (r13_p2['d1'] >= 0)
|
||||
_r13_t25 = r13_p2['d1'];
|
||||
else
|
||||
_r13_t25 = r13_d1;
|
||||
_r13_t26 = r13_d1 = _r13_t25;
|
||||
_r13_t24['call'](_r13_t23, _r13_t26);
|
||||
_r13_t27 = r13_d2s;
|
||||
_r13_t28 = _r13_t27['push'];
|
||||
if (r13_p2['d2'] >= 0)
|
||||
_r13_t29 = r13_p2['d2'];
|
||||
else
|
||||
_r13_t29 = r13_d2;
|
||||
_r13_t30 = r13_d2 = _r13_t29;
|
||||
_r13_t28['call'](_r13_t27, _r13_t30);
|
||||
r13_subSegments['push']([
|
||||
r13_p0,
|
||||
r13_p1,
|
||||
r13_p2
|
||||
]);
|
||||
r13_p0 = r13_p2;
|
||||
r13_j = r13_j + 1;
|
||||
} else
|
||||
void 0;
|
||||
}
|
||||
r13_f1 = r0_Smooth(r13_d1s, { 'method': 'cubic' });
|
||||
r13_f2 = r0_Smooth(r13_d2s, { 'method': 'cubic' });
|
||||
r13_left = [];
|
||||
r13_right = [];
|
||||
r13_j = 0;
|
||||
for (; r13_j < r13_subSegments['length']; r13_j = r13_j + 1) {
|
||||
r13_seg = r13_subSegments[r13_j];
|
||||
if (r13_seg['length'] > 3)
|
||||
_r13_t31 = new r0_Bezier(r13_seg[0]['x'], r13_seg[0]['y'], r13_seg[1]['x'], r13_seg[1]['y'], r13_seg[2]['x'], r13_seg[2]['y'], r13_seg[3]['x'], r13_seg[3]['y']);
|
||||
else
|
||||
_r13_t31 = new r0_Bezier(r13_seg[0]['x'], r13_seg[0]['y'], r13_seg[1]['x'], r13_seg[1]['y'], r13_seg[2]['x'], r13_seg[2]['y']);
|
||||
r13_curve = _r13_t31;
|
||||
_r13_t0 = 0;
|
||||
_r13_t1 = r0_SAMPLES;
|
||||
r13_sample = _r13_t0;
|
||||
for (; r13_sample < _r13_t1; r13_sample = r13_sample + 1) {
|
||||
r13_t = r13_j + r13_sample / r0_SAMPLES;
|
||||
r13_tn = r13_j + (r13_sample + 1) / r0_SAMPLES;
|
||||
r13_lthis = r13_curve['offset'](r13_sample / r0_SAMPLES, r13_f1(r13_t));
|
||||
r13_rthis = r13_curve['offset'](r13_sample / r0_SAMPLES, -r13_f2(r13_t));
|
||||
r13_lnext = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES, r13_f1(r13_tn));
|
||||
r13_rnext = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES, -r13_f2(r13_tn));
|
||||
r13_lnthis1 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY, r13_f1(r13_t + r0_TINY));
|
||||
r13_rnthis1 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY, -r13_f2(r13_t + r0_TINY));
|
||||
r13_lnnext1 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY, r13_f1(r13_tn - r0_TINY));
|
||||
r13_rnnext1 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY, -r13_f2(r13_tn - r0_TINY));
|
||||
r13_lnthis2 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 2, r13_f1(r13_t + r0_TINY * 2));
|
||||
r13_rnthis2 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 2, -r13_f2(r13_t + r0_TINY * 2));
|
||||
r13_lnnext2 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 2, r13_f1(r13_tn - r0_TINY * 2));
|
||||
r13_rnnext2 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 2, -r13_f2(r13_tn - r0_TINY * 2));
|
||||
r13_lnthis3 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 3, r13_f1(r13_t + r0_TINY * 3));
|
||||
r13_rnthis3 = r13_curve['offset'](r13_sample / r0_SAMPLES + r0_TINY * 3, -r13_f2(r13_t + r0_TINY * 3));
|
||||
r13_lnnext3 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 3, r13_f1(r13_tn - r0_TINY * 3));
|
||||
r13_rnnext3 = r13_curve['offset']((r13_sample + 1) / r0_SAMPLES - r0_TINY * 3, -r13_f2(r13_tn - r0_TINY * 3));
|
||||
r13_dlthis = r0_dforward(r13_lthis, r13_lnthis1, r13_lnthis2, r13_lnthis3);
|
||||
r13_drthis = r0_dforward(r13_rthis, r13_rnthis1, r13_rnthis2, r13_rnthis3);
|
||||
r13_dlnext = r0_dbackward(r13_lnext, r13_lnnext1, r13_lnnext2, r13_lnnext3);
|
||||
r13_drnext = r0_dbackward(r13_rnext, r13_rnnext2, r13_rnnext2, r13_rnnext3);
|
||||
r13_il = r0_intersection(r13_lthis['x'], r13_lthis['y'], r13_dlthis['x'], r13_dlthis['y'], r13_lnext['x'], r13_lnext['y'], r13_dlnext['x'], r13_dlnext['y']);
|
||||
r13_ir = r0_intersection(r13_rthis['x'], r13_rthis['y'], r13_drthis['x'], r13_drthis['y'], r13_rnext['x'], r13_rnext['y'], r13_drnext['x'], r13_drnext['y']);
|
||||
if (r13_il['x'] !== null && r13_il['y'] !== null && r0_nonlinear(r13_lthis, r13_il, r13_lnext)) {
|
||||
r13_left['push']({
|
||||
'x': r13_lthis['x'],
|
||||
'y': r13_lthis['y'],
|
||||
'onCurve': true
|
||||
}, {
|
||||
'x': r13_il['x'],
|
||||
'y': r13_il['y'],
|
||||
'onCurve': false
|
||||
});
|
||||
} else {
|
||||
r13_left['push']({
|
||||
'x': r13_lthis['x'],
|
||||
'y': r13_lthis['y'],
|
||||
'onCurve': true
|
||||
});
|
||||
}
|
||||
if (r13_ir['x'] !== null && r13_ir['y'] !== null && r0_nonlinear(r13_rthis, r13_ir, r13_rnext)) {
|
||||
r13_right['push']({
|
||||
'x': r13_rthis['x'],
|
||||
'y': r13_rthis['y'],
|
||||
'onCurve': true
|
||||
}, {
|
||||
'x': r13_ir['x'],
|
||||
'y': r13_ir['y'],
|
||||
'onCurve': false
|
||||
});
|
||||
} else {
|
||||
r13_right['push']({
|
||||
'x': r13_rthis['x'],
|
||||
'y': r13_rthis['y'],
|
||||
'onCurve': true
|
||||
});
|
||||
}
|
||||
}
|
||||
_r13_t32 = r13_left;
|
||||
_r13_t33 = _r13_t32['push'];
|
||||
r13_last = r13_curve['offset'](1, r13_f1(r13_j + 1));
|
||||
_r13_t34 = {
|
||||
'x': r13_last['x'],
|
||||
'y': r13_last['y'],
|
||||
'onCurve': true
|
||||
};
|
||||
_r13_t33['call'](_r13_t32, _r13_t34);
|
||||
_r13_t35 = r13_right;
|
||||
_r13_t36 = _r13_t35['push'];
|
||||
r13_last = r13_curve['offset'](1, -r13_f2(r13_j + 1));
|
||||
_r13_t37 = {
|
||||
'x': r13_last['x'],
|
||||
'y': r13_last['y'],
|
||||
'onCurve': true
|
||||
};
|
||||
_r13_t36['call'](_r13_t35, _r13_t37);
|
||||
}
|
||||
r13_shape = r13_left['concat'](r13_right['reverse']())['map'](function _r13_t38(r15_p) {
|
||||
var r15_p;
|
||||
return {
|
||||
'x': r15_p['x'],
|
||||
'y': r15_p['y'],
|
||||
'onCurve': r15_p['onCurve']
|
||||
};
|
||||
});
|
||||
return [r13_shape];
|
||||
};
|
||||
exports['Stroke'] = r0_Stroke;
|
||||
}
|
158
support/stroke.patel
Normal file
158
support/stroke.patel
Normal file
|
@ -0,0 +1,158 @@
|
|||
define Smooth [require './smooth'].Smooth
|
||||
define intersection [require './intersection'].intersection
|
||||
define Bezier [require 'bezier-js']
|
||||
|
||||
define SAMPLES 4
|
||||
define TINY 0.0001
|
||||
define LITTLE 0.01
|
||||
define KAPPA 0.51
|
||||
define COKAPPA : 1 - KAPPA
|
||||
define BKAPPA : KAPPA + 0.1
|
||||
define COBKAPPA : COKAPPA - 0.1
|
||||
|
||||
define [Stroke] : begin {
|
||||
this.points = ()
|
||||
return this
|
||||
}
|
||||
define [Stroke.bindParameters para] : begin {
|
||||
KAPPA = para.kappa
|
||||
COKAPPA = 1 - KAPPA
|
||||
COBKAPPA = COKAPPA - 0.1
|
||||
BKAPPA = KAPPA + 0.1
|
||||
}
|
||||
define [Stroke.prototype.set-width d1 d2] : begin {
|
||||
local point this.points`[this.points.length - 1]
|
||||
point.d1 = d1
|
||||
point.d2 = d2
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.start-from x y] : begin {
|
||||
this.points = ((.x x .y y .onCurve true))
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.line-to x y] : begin {
|
||||
this.points.push (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.curve-to xc yc x y] : begin {
|
||||
this.points.push (.x xc .y yc .onCurve false) (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.cubic-to x1 y1 x2 y2 x y] : begin {
|
||||
this.points.push (.x x1 .y y1 .onCurve false .cubic true) (.x x2 .y y2 .onCurve false .cubic true) (.x x .y y .onCurve true)
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.arc-vh-to x y] : begin {
|
||||
local last this.points`[this.points.length - 1]
|
||||
this.cubic-to last.x [last.y + BKAPPA * [y - last.y]] [x + BKAPPA * [last.x - x]] y x y
|
||||
return this
|
||||
}
|
||||
define [Stroke.prototype.arc-hv-to x y] : begin {
|
||||
local last this.points`[this.points.length - 1]
|
||||
this.cubic-to [last.x + BKAPPA * [x - last.x]] last.y x [y + BKAPPA * [last.y - y]] x y
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
define [dforward p0 p1 p2 p3] (
|
||||
.x [p0.x + [[-11] / 6 * p0.x + 3 * p1.x - 3 / 2 * p2.x + p3.x / 3] / TINY * LITTLE]
|
||||
.y [p0.y + [[-11] / 6 * p0.y + 3 * p1.y - 3 / 2 * p2.y + p3.y / 3] / TINY * LITTLE]
|
||||
)
|
||||
define [dbackward p0 p1 p2 p3] (
|
||||
.x [p0.x + [11 / 6 * p0.x - 3 * p1.x + 3 / 2 * p2.x - p3.x / 3] / TINY * LITTLE]
|
||||
.y [p0.y + [11 / 6 * p0.y - 3 * p1.y + 3 / 2 * p2.y - p3.y / 3] / TINY * LITTLE]
|
||||
)
|
||||
define [nonlinear a b c] : [Math.abs [[c.y - a.y] * [b.x - a.x] - [c.x - a.x] * [b.y - a.y]]] > TINY
|
||||
|
||||
define [Stroke.prototype.form-stroke d1 d2] : begin {
|
||||
local d1s ([set d1 [if [this.points.0.d1 >= 0] this.points.0.d1 d1]])
|
||||
local d2s ([set d2 [if [this.points.0.d2 >= 0] this.points.0.d2 d2]])
|
||||
local subSegments ()
|
||||
local p0 this.points.0
|
||||
for [local j 1] [j < this.points.length] [inc j] : begin {
|
||||
local p1 this.points`j
|
||||
piecewise {
|
||||
p1.onCurve : begin {
|
||||
subSegments.push (p0 (.x [[p0.x + p1.x] / 2] .y [[p0.y + p1.y] / 2]) p1)
|
||||
d1s.push : set d1 [if [p1.d1 >= 0] p1.d1 d1]
|
||||
d2s.push : set d2 [if [p1.d2 >= 0] p1.d2 d2]
|
||||
p0 = p1
|
||||
}
|
||||
p1.cubic : begin {
|
||||
local p2 this.points`[j + 1]
|
||||
local p3 this.points`[j + 2]
|
||||
d1s.push : set d1 [if [p3.d1 >= 0] p3.d1 d1]
|
||||
d2s.push : set d2 [if [p3.d2 >= 0] p3.d2 d2]
|
||||
subSegments.push (p0 p1 p2 p3)
|
||||
p0 = p3
|
||||
j = j + 2
|
||||
}
|
||||
true : begin {
|
||||
local p2 this.points`[j + 1]
|
||||
d1s.push : set d1 [if [p2.d1 >= 0] p2.d1 d1]
|
||||
d2s.push : set d2 [if [p2.d2 >= 0] p2.d2 d2]
|
||||
subSegments.push (p0 p1 p2)
|
||||
p0 = p2
|
||||
j = j + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
local f1 : Smooth d1s (.method 'cubic')
|
||||
local f2 : Smooth d2s (.method 'cubic')
|
||||
local left ()
|
||||
local right ()
|
||||
for [local j 0] [j < subSegments.length] [inc j] : begin {
|
||||
local seg subSegments`j
|
||||
local curve : if [seg.length > 3] [new Bezier seg.0.x seg.0.y seg.1.x seg.1.y seg.2.x seg.2.y seg.3.x seg.3.y] [new Bezier seg.0.x seg.0.y seg.1.x seg.1.y seg.2.x seg.2.y]
|
||||
foreach sample [range 0 SAMPLES] : begin {
|
||||
local t : j + sample / SAMPLES
|
||||
local tn : j + [sample + 1] / SAMPLES
|
||||
|
||||
local lthis : curve.offset [sample / SAMPLES] [f1 t]
|
||||
local rthis : curve.offset [sample / SAMPLES] [-[f2 t]]
|
||||
|
||||
local lnext : curve.offset [[sample + 1] / SAMPLES] [f1 tn]
|
||||
local rnext : curve.offset [[sample + 1] / SAMPLES] [-[f2 tn]]
|
||||
|
||||
local lnthis1 : curve.offset [sample / SAMPLES + TINY] [f1 [t + TINY]]
|
||||
local rnthis1 : curve.offset [sample / SAMPLES + TINY] [-[f2 [t + TINY]]]
|
||||
local lnnext1 : curve.offset [[sample + 1] / SAMPLES - TINY] [f1 [tn - TINY]]
|
||||
local rnnext1 : curve.offset [[sample + 1] / SAMPLES - TINY] [-[f2 [tn - TINY]]]
|
||||
local lnthis2 : curve.offset [sample / SAMPLES + [TINY * 2]] [f1 [t + [TINY * 2]]]
|
||||
local rnthis2 : curve.offset [sample / SAMPLES + [TINY * 2]] [-[f2 [t + [TINY * 2]]]]
|
||||
local lnnext2 : curve.offset [[sample + 1] / SAMPLES - [TINY * 2]] [f1 [tn - [TINY * 2]]]
|
||||
local rnnext2 : curve.offset [[sample + 1] / SAMPLES - [TINY * 2]] [-[f2 [tn - [TINY * 2]]]]
|
||||
local lnthis3 : curve.offset [sample / SAMPLES + [TINY * 3]] [f1 [t + [TINY * 3]]]
|
||||
local rnthis3 : curve.offset [sample / SAMPLES + [TINY * 3]] [-[f2 [t + [TINY * 3]]]]
|
||||
local lnnext3 : curve.offset [[sample + 1] / SAMPLES - [TINY * 3]] [f1 [tn - [TINY * 3]]]
|
||||
local rnnext3 : curve.offset [[sample + 1] / SAMPLES - [TINY * 3]] [-[f2 [tn - [TINY * 3]]]]
|
||||
|
||||
local dlthis [dforward lthis lnthis1 lnthis2 lnthis3]
|
||||
local drthis [dforward rthis rnthis1 rnthis2 rnthis3]
|
||||
local dlnext [dbackward lnext lnnext1 lnnext2 lnnext3]
|
||||
local drnext [dbackward rnext rnnext2 rnnext2 rnnext3]
|
||||
|
||||
local il : intersection lthis.x lthis.y dlthis.x dlthis.y lnext.x lnext.y dlnext.x dlnext.y
|
||||
local ir : intersection rthis.x rthis.y drthis.x drthis.y rnext.x rnext.y drnext.x drnext.y
|
||||
|
||||
if [[il.x != null] && [il.y != null] && [nonlinear lthis il lnext]] [then {
|
||||
left.push (.x lthis.x .y lthis.y .onCurve true) (.x il.x .y il.y .onCurve false)
|
||||
}] [else {
|
||||
left.push (.x lthis.x .y lthis.y .onCurve true)
|
||||
}]
|
||||
|
||||
if [[ir.x != null] && [ir.y != null] && [nonlinear rthis ir rnext]] [then {
|
||||
right.push (.x rthis.x .y rthis.y .onCurve true) (.x ir.x .y ir.y .onCurve false)
|
||||
}] [else {
|
||||
right.push (.x rthis.x .y rthis.y .onCurve true)
|
||||
}]
|
||||
}
|
||||
left.push [begin [local last [curve.offset 1 [f1 [j + 1]]]] (.x last.x .y last.y .onCurve true)]
|
||||
right.push [begin [local last [curve.offset 1 [-[f2 [j + 1]]]]] (.x last.x .y last.y .onCurve true)]
|
||||
}
|
||||
|
||||
local shape : left.concat [right.reverse] :.map [[p] -> (.x p.x .y p.y .onCurve p.onCurve)]
|
||||
return (shape)
|
||||
}
|
||||
|
||||
exports.Stroke = Stroke
|
Loading…
Reference in New Issue
Block a user