gg: fix gg.draw_rounded_rect_empty() graphical abnormalities and some optimizations (#14186)
							parent
							
								
									b76095f28a
								
							
						
					
					
						commit
						85f616877f
					
				
							
								
								
									
										227
									
								
								vlib/gg/draw.c.v
								
								
								
								
							
							
						
						
									
										227
									
								
								vlib/gg/draw.c.v
								
								
								
								
							| 
						 | 
					@ -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 {
 | 
					 | 
				
			||||||
		theta = theta_coeff * f32(i)
 | 
					 | 
				
			||||||
		xx = r * math.cosf(theta)
 | 
					 | 
				
			||||||
		yy = r * math.sinf(theta)
 | 
					 | 
				
			||||||
		sgl.v2f(xx + lx, yy + ly)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	// right top
 | 
							rad = f32(math.radians(i * 3))
 | 
				
			||||||
	mut rx := nx + width - r
 | 
							dx = r * math.cosf(rad)
 | 
				
			||||||
	mut ry := ny + r
 | 
							dy = r * math.sinf(rad)
 | 
				
			||||||
	for i in rt .. int(segments) {
 | 
							sgl.v2f(ltx - dx, lty - dy)
 | 
				
			||||||
		theta = theta_coeff * f32(i)
 | 
					 | 
				
			||||||
		xx = r * math.cosf(theta)
 | 
					 | 
				
			||||||
		yy = r * math.sinf(theta)
 | 
					 | 
				
			||||||
		sgl.v2f(xx + rx, yy + ry)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// right bottom
 | 
						sgl.end()
 | 
				
			||||||
	mut rbx := rx
 | 
					
 | 
				
			||||||
	mut rby := ny + height - r
 | 
						// right top 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)
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	// left bottom
 | 
							rad = f32(math.radians(i * 3))
 | 
				
			||||||
	mut lbx := lx
 | 
							dx = r * math.cosf(rad)
 | 
				
			||||||
	mut lby := ny + height - r
 | 
							dy = r * math.sinf(rad)
 | 
				
			||||||
	for i in lb .. lt {
 | 
							sgl.v2f(rtx + dx, rty - dy)
 | 
				
			||||||
		theta = theta_coeff * f32(i)
 | 
					 | 
				
			||||||
		xx = r * math.cosf(theta)
 | 
					 | 
				
			||||||
		yy = r * math.sinf(theta)
 | 
					 | 
				
			||||||
		sgl.v2f(xx + lbx, yy + lby)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sgl.v2f(lx + xx, ly)
 | 
						sgl.end()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// right bottom quarter
 | 
				
			||||||
 | 
						sgl.begin_line_strip()
 | 
				
			||||||
 | 
						for i in 0 .. 31 {
 | 
				
			||||||
 | 
							if r == 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rad = f32(math.radians(i * 3))
 | 
				
			||||||
 | 
							dx = r * math.cosf(rad)
 | 
				
			||||||
 | 
							dy = r * math.sinf(rad)
 | 
				
			||||||
 | 
							sgl.v2f(rbx + dx, rby + dy)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sgl.end()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// left bottom quarter
 | 
				
			||||||
 | 
						sgl.begin_line_strip()
 | 
				
			||||||
 | 
						for i in 0 .. 31 {
 | 
				
			||||||
 | 
							if r == 0 {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rad = f32(math.radians(i * 3))
 | 
				
			||||||
 | 
							dx = r * math.cosf(rad)
 | 
				
			||||||
 | 
							dy = r * math.sinf(rad)
 | 
				
			||||||
 | 
							sgl.v2f(lbx - dx, lby + dy)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						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()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue