mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
gg: improve small circle (r<20) looks
This commit is contained in:
parent
469282b20d
commit
0979723636
@ -1,6 +1,5 @@
|
||||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
||||
|
||||
module gg
|
||||
|
||||
import gx
|
||||
@ -374,21 +373,35 @@ pub fn (ctx &Context) draw_square_filled(x f32, y f32, s f32, c gx.Color) {
|
||||
|
||||
//---- circle
|
||||
|
||||
const circle_segment_size = 8.35
|
||||
// The table here is derived by looking at the result of vlib/gg/testdata/tweak_circles.vv
|
||||
// and then choosing the most circle-ish drawing with the minimum number of segments.
|
||||
const small_circle_segments = [0, 2, 4, 6, 6, 8, 8, 13, 10, 18, 12, 12, 10, 13, 16, 15, 16]!
|
||||
|
||||
[direct_array_access]
|
||||
fn radius_to_segments(r f32) int {
|
||||
if r < 30.0 {
|
||||
ir := int(math.ceil(r))
|
||||
if ir > 0 && ir < gg.small_circle_segments.len {
|
||||
return gg.small_circle_segments[ir]
|
||||
}
|
||||
return ir
|
||||
}
|
||||
return int(math.ceil(2 * math.pi * r / 8))
|
||||
}
|
||||
|
||||
// draw_circle_empty draws an empty circle
|
||||
pub fn (ctx &Context) draw_circle_empty(x f32, y f32, r f32, c gx.Color) {
|
||||
pub fn (ctx &Context) draw_circle_empty(x f32, y f32, radius f32, c gx.Color) {
|
||||
if c.a != 255 {
|
||||
sgl.load_pipeline(ctx.timage_pip)
|
||||
}
|
||||
nx := x * ctx.scale
|
||||
ny := y * ctx.scale
|
||||
nr := r * ctx.scale
|
||||
nr := radius * ctx.scale
|
||||
mut theta := f32(0)
|
||||
mut xx := f32(0)
|
||||
mut yy := f32(0)
|
||||
|
||||
segments := math.ceil(2 * math.pi * r / gg.circle_segment_size)
|
||||
segments := radius_to_segments(radius)
|
||||
|
||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||
sgl.begin_line_strip()
|
||||
@ -402,20 +415,19 @@ pub fn (ctx &Context) draw_circle_empty(x f32, y f32, r f32, c gx.Color) {
|
||||
}
|
||||
|
||||
// draw_circle_filled draws a filled circle
|
||||
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, r f32, c gx.Color) {
|
||||
segments := int(math.ceil(2 * math.pi * r / gg.circle_segment_size))
|
||||
ctx.draw_circle_with_segments(x, y, r, segments, c)
|
||||
pub fn (ctx &Context) draw_circle_filled(x f32, y f32, radius f32, c gx.Color) {
|
||||
ctx.draw_circle_with_segments(x, y, radius, radius_to_segments(radius), c)
|
||||
}
|
||||
|
||||
// draw_circle_with_segments draws a circle with a specific number of segments (affects how smooth/round the circle is)
|
||||
pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, r f32, segments int, c gx.Color) {
|
||||
pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, radius f32, segments int, c gx.Color) {
|
||||
if c.a != 255 {
|
||||
sgl.load_pipeline(ctx.timage_pip)
|
||||
}
|
||||
sgl.c4b(c.r, c.g, c.b, c.a)
|
||||
nx := x * ctx.scale
|
||||
ny := y * ctx.scale
|
||||
nr := r * ctx.scale
|
||||
nr := radius * ctx.scale
|
||||
mut theta := f32(0)
|
||||
mut xx := f32(0)
|
||||
mut yy := f32(0)
|
||||
@ -433,7 +445,7 @@ pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, r f32, segments in
|
||||
pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) {
|
||||
$if macos {
|
||||
if ctx.native_rendering {
|
||||
C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), r, c)
|
||||
C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), radius, c)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -488,7 +500,7 @@ pub fn (ctx &Context) draw_slice_empty(x f32, y f32, outer_radius f32, start_ang
|
||||
}
|
||||
|
||||
// draw_slice_filled draws a filled circle slice/pie
|
||||
pub fn (ctx &Context) draw_slice_filled(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
pub fn (ctx &Context) draw_slice_filled(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
if c.a != 255 {
|
||||
sgl.load_pipeline(ctx.timage_pip)
|
||||
}
|
||||
@ -498,8 +510,8 @@ pub fn (ctx &Context) draw_slice_filled(x f32, y f32, r f32, start_angle f32, en
|
||||
theta := f32(end_angle / f32(segments))
|
||||
tan_factor := math.tanf(theta)
|
||||
rad_factor := math.cosf(theta)
|
||||
mut xx := r * math.cosf(start_angle)
|
||||
mut yy := r * math.sinf(start_angle)
|
||||
mut xx := radius * math.cosf(start_angle)
|
||||
mut yy := radius * math.sinf(start_angle)
|
||||
sgl.begin_triangle_strip()
|
||||
for i := 0; i < segments + 1; i++ {
|
||||
sgl.v2f(xx + nx, yy + ny)
|
||||
@ -764,18 +776,18 @@ pub fn (ctx &Context) draw_square(x f32, y f32, s f32, c gx.Color) {
|
||||
}
|
||||
|
||||
[deprecated: 'use draw_circle_filled() instead']
|
||||
pub fn (ctx &Context) draw_circle(x f32, y f32, r f32, c gx.Color) {
|
||||
ctx.draw_circle_filled(x, y, r, c)
|
||||
pub fn (ctx &Context) draw_circle(x f32, y f32, radius f32, c gx.Color) {
|
||||
ctx.draw_circle_filled(x, y, radius, c)
|
||||
}
|
||||
|
||||
[deprecated: 'use draw_slice_empty() instead']
|
||||
pub fn (ctx &Context) draw_empty_slice(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
ctx.draw_slice_empty(x, y, r, start_angle, end_angle, segments, c)
|
||||
pub fn (ctx &Context) draw_empty_slice(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
ctx.draw_slice_empty(x, y, radius, start_angle, end_angle, segments, c)
|
||||
}
|
||||
|
||||
[deprecated: 'use draw_slice_filled() instead']
|
||||
pub fn (ctx &Context) draw_slice(x f32, y f32, r f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
ctx.draw_slice_filled(x, y, r, start_angle, end_angle, segments, c)
|
||||
pub fn (ctx &Context) draw_slice(x f32, y f32, radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
|
||||
ctx.draw_slice_filled(x, y, radius, start_angle, end_angle, segments, c)
|
||||
}
|
||||
|
||||
[deprecated: 'use draw_arc_empty() instead']
|
||||
|
49
vlib/gg/testdata/tweak_circles.vv
vendored
Normal file
49
vlib/gg/testdata/tweak_circles.vv
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
module main
|
||||
|
||||
import gg
|
||||
import gx
|
||||
|
||||
struct App {
|
||||
mut:
|
||||
gg &gg.Context = 0
|
||||
radius f64 = 10.0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut app := &App{}
|
||||
app.gg = gg.new_context(
|
||||
bg_color: gx.white
|
||||
width: 300
|
||||
height: 300
|
||||
window_title: 'Circles'
|
||||
frame_fn: frame
|
||||
event_fn: on_event
|
||||
user_data: app
|
||||
)
|
||||
app.gg.run()
|
||||
}
|
||||
|
||||
fn on_event(e &gg.Event, mut app App) {
|
||||
match e.typ {
|
||||
.key_down {
|
||||
match e.key_code {
|
||||
.up {
|
||||
app.radius += 1
|
||||
}
|
||||
.down {
|
||||
app.radius -= 1
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
fn frame(mut app App) {
|
||||
app.gg.begin()
|
||||
app.gg.draw_circle_empty(150, 150, f32(app.radius), gx.blue)
|
||||
app.gg.draw_text(20, 20, 'radius: $app.radius')
|
||||
// app.gg.draw_text(20, 50, 'circle_segment_size: $circle_segment_size')
|
||||
app.gg.end()
|
||||
}
|
Loading…
Reference in New Issue
Block a user