Iosevka/support/simple-expand.ptl
2015-12-18 23:20:02 +08:00

96 lines
3.9 KiB
Plaintext

import 'bezier-js' as Bezier
define TINY 0.001
define LITTLE 0.01
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 [computeOffsetPoint curve t offset] : begin
local onpoint : curve.compute t
local normal : curve.normal t
return {.x onpoint.x + offset * normal.x .y onpoint.y + offset * normal.y}
define [intersection z1 c1 c2 z2] : begin
define d1 {.x (c1.x - z1.x) .y (c1.y - z1.y)}
define d2 {.x (c2.x - z2.x) .y (c2.y - z2.y)}
local det : d2.x * d1.y - d2.y * d1.x
if ([Math.abs det] <= 1e-8) : return null
local u : ((z2.y - z1.y) * d2.x - (z2.x - z1.x) * d2.y) / det
local v : ((z2.y - z1.y) * d1.x - (z2.x - z1.x) * d1.y) / det
if (u <= 0 || v <= 0) : return null
return { .x (z1.x + d1.x * u), .y (z1.y + d1.y * u) }
export all : define [strokeExpand points f1 f2 samples] : begin
local shapes {}
local subSegments {}
local p0 points.0
for [local j 1] (j < points.length) [inc j] : begin
local p1 points.(j)
piecewise
p1.onCurve : begin
subSegments.push : local seg : new Bezier p0.x p0.y ((p0.x + p1.x) / 2) ((p0.y + p1.y) / 2) p1.x p1.y
p0 = p1
p1.cubic : begin
local p2 points.((j + 1))
local p3 points.((j + 2))
subSegments.push : local seg : new Bezier p0.x p0.y p1.x p1.y p2.x p2.y p3.x p3.y
p0 = p3
j = j + 2
true : begin
local p2 points.((j + 1))
subSegments.push : local seg : new Bezier p0.x p0.y p1.x p1.y p2.x p2.y
p0 = p2
j = j + 1
local left {}
local right {}
for [local j 0] (j < subSegments.length) [inc j] : begin
local curve subSegments.(j)
left.push [begin [local last [computeOffsetPoint curve 0 f1]] {.x last.x .y last.y .onCurve true}]
right.push [begin [local last [computeOffsetPoint curve 0 f2]] {.x last.x .y last.y .onCurve true}]
foreach sample [range 0 samples] : begin
local t : sample / samples
local tn : (sample + 1) / samples
local lthis : computeOffsetPoint curve t f1
local rthis : computeOffsetPoint curve t f2
local lnext : computeOffsetPoint curve tn f1
local rnext : computeOffsetPoint curve tn f2
local lnthis1 : computeOffsetPoint curve (t + TINY) f1
local rnthis1 : computeOffsetPoint curve (t + TINY) f2
local lnnext1 : computeOffsetPoint curve (tn - TINY) f1
local rnnext1 : computeOffsetPoint curve (tn - TINY) f2
local lnthis2 : computeOffsetPoint curve (t + 2 * TINY) f1
local rnthis2 : computeOffsetPoint curve (t + 2 * TINY) f2
local lnnext2 : computeOffsetPoint curve (tn - 2 * TINY) f1
local rnnext2 : computeOffsetPoint curve (tn - 2 * TINY) f2
local lnthis3 : computeOffsetPoint curve (t + 3 * TINY) f1
local rnthis3 : computeOffsetPoint curve (t + 3 * TINY) f2
local lnnext3 : computeOffsetPoint curve (tn - 3 * TINY) f1
local rnnext3 : computeOffsetPoint curve (tn - 3 * TINY) f2
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 dlthis lnext dlnext
if il
: then : left.push {.x il.x .y il.y .onCurve false} {.x lnext.x .y lnext.y .onCurve true}
: else : left.push {.x lnext.x .y lnext.y .onCurve true}
local ir : intersection rthis drthis rnext drnext
if ir
: then : right.push {.x ir.x .y ir.y .onCurve false} {.x rnext.x .y rnext.y .onCurve true}
: else : right.push {.x rnext.x .y rnext.y .onCurve true}
shapes.push : left.concat [right.reverse]
return shapes