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 { | 		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() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue