gg: fix gg.draw_rounded_rect_empty() graphical abnormalities and some optimizations (#14186)

tzSharing 2022-04-27 16:22:57 +08:00 committed by Jef Roosens
parent c37bb48e9c
commit 604f4f5e44
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
1 changed files with 138 additions and 89 deletions

View File

@ -211,66 +211,111 @@ pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) {
sgl.end() sgl.end()
} }
// draw_rounded_rect_empty draws the outline of a rounded rectangle // draw_rounded_rect_empty draws the outline of a rounded rectangle with a thickness of 1 px.
// `x`,`y` is the top-left corner of the rectangle. // `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height. // `w` is the width, `h` is the height.
// `radius` is the radius of the corner-rounding in pixels. // `radius` is the radius of the corner-rounding in pixels.
// `c` is the color of the outline. // `c` is the color of the outline.
pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius f32, c gx.Color) { pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
mut theta := f32(0) if w <= 0 || h <= 0 || radius < 0 {
mut xx := f32(0) return
mut yy := f32(0) }
r := radius * ctx.scale if c.a != 255 {
nx := x * ctx.scale sgl.load_pipeline(ctx.timage_pip)
ny := y * ctx.scale }
sgl.c4b(c.r, c.g, c.b, c.a)
mut new_radius := radius
if w >= h && radius > h / 2 {
new_radius = h / 2
} else if radius > w / 2 {
new_radius = w / 2
}
r := new_radius * ctx.scale
sx := x * ctx.scale // start point x
sy := y * ctx.scale
width := w * ctx.scale width := w * ctx.scale
height := h * ctx.scale height := h * ctx.scale
segments := 2 * math.pi * r // circle center coordinates
segdiv := segments / 4 ltx := sx + r
rb := 0 lty := sy + r
lb := int(rb + segdiv) rtx := sx + width - r
lt := int(lb + segdiv) rty := lty
rt := int(lt + segdiv) rbx := rtx
sgl.c4b(c.r, c.g, c.b, c.a) rby := sy + height - r
lbx := ltx
lby := rby
mut rad := f32(0)
mut dx := f32(0)
mut dy := f32(0)
// left top quarter
sgl.begin_line_strip() sgl.begin_line_strip()
// left top for i in 0 .. 31 {
lx := nx + r if r == 0 {
ly := ny + r break
theta_coeff := 2 * f32(math.pi) / segments }
for i in lt .. rt { rad = f32(math.radians(i * 3))
theta = theta_coeff * f32(i) dx = r * math.cosf(rad)
xx = r * math.cosf(theta) dy = r * math.sinf(rad)
yy = r * math.sinf(theta) sgl.v2f(ltx - dx, lty - dy)
sgl.v2f(xx + lx, yy + ly)
} }
// right top sgl.end()
mut rx := nx + width - r
mut ry := ny + r // right top quarter
for i in rt .. int(segments) { sgl.begin_line_strip()
theta = theta_coeff * f32(i) for i in 0 .. 31 {
xx = r * math.cosf(theta) if r == 0 {
yy = r * math.sinf(theta) break
sgl.v2f(xx + rx, yy + ry) }
rad = f32(math.radians(i * 3))
dx = r * math.cosf(rad)
dy = r * math.sinf(rad)
sgl.v2f(rtx + dx, rty - dy)
} }
// right bottom sgl.end()
mut rbx := rx
mut rby := ny + height - r // right bottom quarter
for i in rb .. lb { sgl.begin_line_strip()
theta = theta_coeff * f32(i) for i in 0 .. 31 {
xx = r * math.cosf(theta) if r == 0 {
yy = r * math.sinf(theta) break
sgl.v2f(xx + rbx, yy + rby) }
rad = f32(math.radians(i * 3))
dx = r * math.cosf(rad)
dy = r * math.sinf(rad)
sgl.v2f(rbx + dx, rby + dy)
} }
// left bottom sgl.end()
mut lbx := lx
mut lby := ny + height - r // left bottom quarter
for i in lb .. lt { sgl.begin_line_strip()
theta = theta_coeff * f32(i) for i in 0 .. 31 {
xx = r * math.cosf(theta) if r == 0 {
yy = r * math.sinf(theta) break
sgl.v2f(xx + lbx, yy + lby) }
rad = f32(math.radians(i * 3))
dx = r * math.cosf(rad)
dy = r * math.sinf(rad)
sgl.v2f(lbx - dx, lby + dy)
} }
sgl.v2f(lx + xx, ly) sgl.end()
// Currently don't use 'gg.draw_line()' directly, it will repeatedly execute '*ctx.scale'.
sgl.begin_lines()
// top
sgl.v2f(ltx, sy)
sgl.v2f(rtx, sy)
// right
sgl.v2f(rtx + r, rty)
sgl.v2f(rtx + r, rby)
// bottom
sgl.v2f(lbx, lby + r)
sgl.v2f(rbx, rby + r)
// left
sgl.v2f(sx, lty)
sgl.v2f(sx, lby)
sgl.end() sgl.end()
} }
@ -280,87 +325,91 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
// `radius` is the radius of the corner-rounding in pixels. // `radius` is the radius of the corner-rounding in pixels.
// `c` is the color of the filled. // `c` is the color of the filled.
pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) { pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
assert w > 0 && h > 0 && radius >= 0 if w <= 0 || h <= 0 || radius < 0 {
return
}
if c.a != 255 { if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip) sgl.load_pipeline(ctx.timage_pip)
} }
sgl.c4b(c.r, c.g, c.b, c.a) sgl.c4b(c.r, c.g, c.b, c.a)
mut xx := f32(0)
mut yy := f32(0)
mut radians := f32(0)
mut new_radius := radius mut new_radius := radius
if w >= h && radius > h / 2 { if w >= h && radius > h / 2 {
new_radius = h / 2 new_radius = h / 2
} else if radius > w / 2 { } else if radius > w / 2 {
new_radius = w / 2 new_radius = w / 2
} }
r := new_radius * ctx.scale r := new_radius * ctx.scale
nx := x * ctx.scale sx := x * ctx.scale // start point x
ny := y * ctx.scale sy := y * ctx.scale
width := w * ctx.scale width := w * ctx.scale
height := h * ctx.scale height := h * ctx.scale
// circle center coordinates
ltx := sx + r
lty := sy + r
rtx := sx + width - r
rty := lty
rbx := rtx
rby := sy + height - r
lbx := ltx
lby := rby
mut rad := f32(0)
mut dx := f32(0)
mut dy := f32(0)
// left top quarter // left top quarter
sgl.begin_triangle_strip() sgl.begin_triangle_strip()
ltx := nx + r for i in 0 .. 31 {
lty := ny + r
for i in 0 .. 91 {
if r == 0 { if r == 0 {
break break
} }
radians = f32(math.radians(i)) rad = f32(math.radians(i * 3))
xx = r * math.cosf(radians) dx = r * math.cosf(rad)
yy = r * math.sinf(radians) dy = r * math.sinf(rad)
sgl.v2f(ltx - xx, lty - yy) sgl.v2f(ltx - dx, lty - dy)
sgl.v2f(ltx, lty) sgl.v2f(ltx, lty)
} }
sgl.end() sgl.end()
// right top quarter // right top quarter
sgl.begin_triangle_strip() sgl.begin_triangle_strip()
rtx := nx + width - r for i in 0 .. 31 {
rty := ny + r
for i in 0 .. 91 {
if r == 0 { if r == 0 {
break break
} }
radians = f32(math.radians(i)) rad = f32(math.radians(i * 3))
xx = r * math.cosf(radians) dx = r * math.cosf(rad)
yy = r * math.sinf(radians) dy = r * math.sinf(rad)
sgl.v2f(rtx + xx, rty - yy) sgl.v2f(rtx + dx, rty - dy)
sgl.v2f(rtx, rty) sgl.v2f(rtx, rty)
} }
sgl.end() sgl.end()
// right bottom quarter // right bottom quarter
sgl.begin_triangle_strip() sgl.begin_triangle_strip()
rbx := nx + width - r for i in 0 .. 31 {
rby := ny + height - r
for i in 0 .. 91 {
if r == 0 { if r == 0 {
break break
} }
radians = f32(math.radians(i)) rad = f32(math.radians(i * 3))
xx = r * math.cosf(radians) dx = r * math.cosf(rad)
yy = r * math.sinf(radians) dy = r * math.sinf(rad)
sgl.v2f(rbx + xx, rby + yy) sgl.v2f(rbx + dx, rby + dy)
sgl.v2f(rbx, rby) sgl.v2f(rbx, rby)
} }
sgl.end() sgl.end()
// left bottom quarter // left bottom quarter
sgl.begin_triangle_strip() sgl.begin_triangle_strip()
lbx := nx + r for i in 0 .. 31 {
lby := ny + height - r
for i in 0 .. 91 {
if r == 0 { if r == 0 {
break break
} }
radians = f32(math.radians(i)) rad = f32(math.radians(i * 3))
xx = r * math.cosf(radians) dx = r * math.cosf(rad)
yy = r * math.sinf(radians) dy = r * math.sinf(rad)
sgl.v2f(lbx - xx, lby + yy) sgl.v2f(lbx - dx, lby + dy)
sgl.v2f(lbx, lby) sgl.v2f(lbx, lby)
} }
sgl.end() sgl.end()
@ -368,24 +417,24 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
// Separate drawing is to prevent transparent color overlap // Separate drawing is to prevent transparent color overlap
// top rectangle // top rectangle
sgl.begin_quads() sgl.begin_quads()
sgl.v2f(ltx, ny) sgl.v2f(ltx, sy)
sgl.v2f(rtx, ny) sgl.v2f(rtx, sy)
sgl.v2f(rtx, rty) sgl.v2f(rtx, rty)
sgl.v2f(ltx, lty) sgl.v2f(ltx, lty)
sgl.end() sgl.end()
// middle rectangle // middle rectangle
sgl.begin_quads() sgl.begin_quads()
sgl.v2f(nx, ny + r) sgl.v2f(sx, lty)
sgl.v2f(rtx + r, rty) sgl.v2f(rtx + r, rty)
sgl.v2f(rbx + r, rby) sgl.v2f(rbx + r, rby)
sgl.v2f(nx, lby) sgl.v2f(sx, lby)
sgl.end() sgl.end()
// bottom rectangle // bottom rectangle
sgl.begin_quads() sgl.begin_quads()
sgl.v2f(lbx, lby) sgl.v2f(lbx, lby)
sgl.v2f(rbx, rby) sgl.v2f(rbx, rby)
sgl.v2f(rbx, ny + height) sgl.v2f(rbx, rby + r)
sgl.v2f(lbx, ny + height) sgl.v2f(lbx, rby + r)
sgl.end() sgl.end()
} }