pixie/experiments/rounded_rect.nim

124 lines
3.4 KiB
Nim
Raw Normal View History

2021-12-05 01:42:47 +00:00
import benchy, chroma, pixie, pixie/internal, strformat
import benchy, chroma, pixie
proc newRoundedRectImage1(w, h, r: int, color: Color): Image =
result = newImage(w, h)
let ctx = newContext(result)
ctx.fillStyle = color(0, 1, 0, 1)
let
pos = vec2(0, 0)
wh = vec2(w.float32, h.float32)
r = r.float32
ctx.fillRoundedRect(rect(pos, wh), r)
proc newRoundedRectImage15(w, h, r: int, color: Color): Image =
let path = newPath()
let
pos = vec2(0, 0)
wh = vec2(w.float32, h.float32)
r = r.float32
path.roundedRect(rect(pos, wh), r, r, r, r)
result = path.fillImage(w, h, color(0, 1, 0, 1))
proc newRoundedRectImage2(w, h, r: int, color: Color): Image =
result = newImage(w, h)
result.fill(color)
let
w1 = w - 1
h1 = h - 1
for y in 0 ..< r:
for x in 0 ..< r:
var a: float32 = 0
for s in 0 ..< 5:
let
yc = y.float32 + s.float32 / 5 + (1 / 5 / 2)
xc = r.float32 - sqrt(r.float32*r.float32 - (yc - r.float32) ^ 2)
let mid = (x.float32 - xc + 1).clamp(0, 1)
a += 1/5 * mid
if a < 1:
var c = color
c.a = a
let cx = c.rgbx
result.setRgbaUnsafe(x, y, cx)
result.setRgbaUnsafe(w1 - x, y, cx)
result.setRgbaUnsafe(w1 - x, h1 - y, cx)
result.setRgbaUnsafe(x, h1 - y, cx)
proc newRoundedRectImage3(w, h, r: int, color: Color): Image =
result = newImage(w, h)
result.fill(color)
if r == 0:
return
const
q = 5
qf = q.float32
qoffset: float32 = (1 / qf / 2)
let
r = r.clamp(0, min(w, h) div 2)
rf = r.float32
w1 = w - 1
h1 = h - 1
rgbx = color.rgbx
channels = [rgbx.r.uint32, rgbx.g.uint32, rgbx.b.uint32, rgbx.a.uint32]
var coverage = newSeq[uint8](r)
for y in 0 ..< r:
zeroMem(coverage[0].addr, coverage.len)
var yf: float32 = y.float32 + qoffset
for m in 0 ..< q:
let hit = sqrt(rf^2 - yf^2)
coverage[hit.int] += max((1 - (hit - hit.trunc)) * 255 / qf, 0).uint8
for x in hit.int + 1 ..< r:
coverage[x] += (255 div q).uint8
yf += 1 / qf
for x in 0 ..< r:
let coverage = 255 - coverage[x]
if coverage != 255:
var cx: ColorRGBX
cx.r = ((channels[0] * coverage) div 255).uint8
cx.g = ((channels[1] * coverage) div 255).uint8
cx.b = ((channels[2] * coverage) div 255).uint8
cx.a = ((channels[3] * coverage) div 255).uint8
let
xn = r - x - 1
yn = r - y - 1
result.setRgbaUnsafe(xn, yn, cx)
result.setRgbaUnsafe(w1 - xn, yn, cx)
result.setRgbaUnsafe(w1 - xn, h1 - yn, cx)
result.setRgbaUnsafe(xn, h1 - yn, cx)
const r = 16
let img1 = newRoundedRectImage1(200, 200, r, color(0, 1, 0, 1))
img1.writeFile("rrect_current.png")
let img2 = newRoundedRectImage3(200, 200, r, color(0, 1, 0, 1))
img2.writeFile("rrect_new.png")
let (diffScore, diffImage) = diff(img1, img2)
echo &"score: {diffScore}"
diffImage.writeFile("rrect_diff.png")
timeIt "fill rounded rect via path 1":
for i in 0 ..< 10:
discard newRoundedRectImage1(200, 200, r, color(0, 1, 0, 1))
timeIt "fill rounded rect via path 1.5":
for i in 0 ..< 10:
discard newRoundedRectImage15(200, 200, r, color(0, 1, 0, 1))
timeIt "fill rounded rect via math 2":
for i in 0 ..< 10:
discard newRoundedRectImage2(200, 200, 50, color(0, 1, 0, 1))
timeIt "fill rounded rect via math 3":
for i in 0 ..< 10:
discard newRoundedRectImage3(200, 200, r, color(0, 1, 0, 1))