ref: 86a1bffad7063d1f51dfe44c2126bbdf8b7fe5c8
dir: /worklet.js/
class StackBlockPaint {
static inputProperties = ["--color", "font-size", "--hat", "--cap", "--mouth-above", "--mouth-below", "--define"]
paint(ctx, {width, height}, properties)
{
let isHat = properties.get("--hat")?.[0]
let isCap = properties.get("--cap")?.[0]
let isDefine = properties.get("--define")?.[0]
let hasMouthAbove = properties.get("--mouth-above")?.[0]
let hasMouthBelow = properties.get("--mouth-below")?.[0]
let color = String(properties.get("--color"))
let darker = `oklab(from ${color} calc(l - 0.25) a b)`
let size = Number(properties.get("font-size").to("px").value)
let x0 = 0
let y0 = 0
let x1 = width
let y1 = height + 2
y1 -= size / 2
if (isHat) y0 += size
if (hasMouthAbove) y0 += size / 2 - 2
function drawBlock1()
{
ctx.beginPath()
drawBlock(ctx, x0, y0, x1, y1, size, {isHat, isCap, hasMouthBelow, hasMouthAbove, isDefine})
}
drawBlock1()
ctx.clip()
ctx.rect(0, 0, width, height)
ctx.fillStyle = color
ctx.fill()
if (!hasMouthAbove) {
let gradient = ctx.createLinearGradient(x0, y0, x0, y1)
gradient.addColorStop(0, "#FFF4")
gradient.addColorStop(0.75, "#FFF0")
ctx.fillStyle = gradient
ctx.fill()
}
if (hasMouthAbove && !hasMouthBelow) {
let gradient = ctx.createLinearGradient(x0, y0, x0, y1)
gradient.addColorStop(0.25, "#0000")
gradient.addColorStop(1, "#0001")
ctx.fillStyle = gradient
ctx.fill()
}
drawBlock1()
ctx.strokeStyle = darker
ctx.lineWidth = 4
ctx.stroke()
if (isHat || isDefine) return
let x2 = 2
if (hasMouthAbove) x2 += size + 2
let gradient = ctx.createLinearGradient(x0, y0, x0, y0 + 100)
gradient.addColorStop(0.02, darker)
gradient.addColorStop(size / 100, "#222")
ctx.beginPath()
ctx.moveTo(size * 3 + x2, 0)
ctx.lineTo(size * 3 + x2, 2)
drawKnub(ctx, size + x2, y0 + 2, size * 2.5 + x2 + 2, y0 + size / 2)
ctx.lineTo(x0 + x2 + size, y0)
ctx.fillStyle = gradient
ctx.fill()
}
}
class BooleanBlockPaint {
static inputProperties = ["--color"]
paint(ctx, {width, height}, properties)
{
let color = String(properties.get("--color"))
let darker = `oklab(from ${color} calc(l - 0.25) a b)`
ctx.moveTo(0, height / 2)
ctx.lineTo(height / 2, 0)
ctx.lineTo(width - height / 2, 0)
ctx.lineTo(width, height / 2)
ctx.lineTo(width - height / 2, height)
ctx.lineTo(height / 2, height)
ctx.closePath()
ctx.clip()
ctx.fillStyle = color
ctx.fill()
let gradient = ctx.createLinearGradient(0, 0, 0, height)
gradient.addColorStop(0, "#FFF4")
gradient.addColorStop(0.75, "#FFF0")
ctx.fillStyle = gradient
ctx.fill()
ctx.strokeStyle = darker
ctx.lineWidth = 4
ctx.stroke()
}
}
registerPaint("stack-block", StackBlockPaint)
registerPaint("boolean-block", BooleanBlockPaint)
function drawBlock(ctx, x0, y0, x1, y1, size, {isHat, isCap, hasMouthBelow, hasMouthAbove, isDefine})
{
let x2 = 2
if (hasMouthBelow) x2 += size + 2
let radius = size / 2
let radius2 = radius
if (isDefine) radius2 += size
if (isHat) {
ctx.moveTo(x0, y0 + size / 2)
ctx.quadraticCurveTo(x0, y0 - size, x0 + size * 3, y0 - size)
ctx.bezierCurveTo(x0 + size * 5, y0 - size, x0 + size * 6, y0, x0 + size * 8, y0)
}
else {
if (hasMouthAbove) {
ctx.moveTo(x0, y0 - radius * 2)
ctx.lineTo(x0 + size + 4, y0 - radius * 2)
ctx.arcTo(x0 + size + 4, y0, x0 + size * 2, y0, radius / 1.25)
}
else {
ctx.moveTo(x0, y0 + radius)
ctx.arcTo(x0, y0, x0 + radius, y0, radius2)
}
}
ctx.arcTo(x1, y0, x1, y1, radius2)
ctx.arcTo(x1, y1, x0, y1, radius)
if (!isCap) drawKnub(ctx, x0 + size + x2, y1, x0 + size * 2.5 + x2 + 2, y1 + size / 2 - 2)
if (hasMouthBelow) {
ctx.lineTo(x0 + size + radius / 1.25 + 4, y1)
ctx.arcTo(x0 + size + 4, y1, x0 + size + 4, y1 + radius / 1.25, radius / 1.25)
ctx.lineTo(x0 + size + 4, y1 + size)
ctx.lineTo(x0, y1 + size)
}
else {
ctx.arcTo(x0, y1, x0, y0, radius)
}
ctx.closePath()
}
function drawKnub(ctx, x0, y0, x1, y1)
{
let radius = (y1 - y0) / 2
x1 -= radius
ctx.arcTo(x1 + radius, y0, x1, y1 - radius / 2, radius / 2)
ctx.arcTo(x1, y1, x0, y1, radius * 1.5)
ctx.arcTo(x0 + radius, y1, x0, y0, radius * 1.5)
ctx.arcTo(x0, y0, x0 - radius / 2, y0, radius / 2)
}