Skip to content

Commit

Permalink
gg: document all draw functions (#13931)
Browse files Browse the repository at this point in the history
  • Loading branch information
Larpon committed Apr 4, 2022
1 parent 5369379 commit aa9e2eb
Showing 1 changed file with 103 additions and 39 deletions.
142 changes: 103 additions & 39 deletions vlib/gg/draw.c.v
Expand Up @@ -7,8 +7,11 @@ import sokol
import sokol.sgl
import math

//---- pixel

// draw_pixel draws one pixel on the screen.
//
// NOTE calling this function frequently is very *inefficient*,
// for drawing shapes it's recommended to draw whole primitives with
// functions like `draw_rect_empty` or `draw_triangle_empty` etc.
[inline]
pub fn (ctx &Context) draw_pixel(x f32, y f32, c gx.Color) {
if c.a != 255 {
Expand All @@ -21,7 +24,11 @@ pub fn (ctx &Context) draw_pixel(x f32, y f32, c gx.Color) {
sgl.end()
}

// Sets pixels from an array of points [x, y, x2, y2, etc...]
// draw_pixels draws pixels from an array of points [x, y, x2, y2, etc...]
//
// NOTE calling this function frequently is very *inefficient*,
// for drawing shapes it's recommended to draw whole primitives with
// functions like `draw_rect_empty` or `draw_triangle_empty` etc.
[direct_array_access; inline]
pub fn (ctx &Context) draw_pixels(points []f32, c gx.Color) {
assert points.len % 2 == 0
Expand All @@ -40,9 +47,7 @@ pub fn (ctx &Context) draw_pixels(points []f32, c gx.Color) {
sgl.end()
}

//---- line

// Draws a line between the points provided
// draw_line draws a line between the points `x,y` and `x2,y2` in color `c`.
pub fn (ctx &Context) draw_line(x f32, y f32, x2 f32, y2 f32, c gx.Color) {
$if macos {
if ctx.native_rendering {
Expand All @@ -68,7 +73,7 @@ pub fn (ctx &Context) draw_line(x f32, y f32, x2 f32, y2 f32, c gx.Color) {
sgl.end()
}

// Draws a line between the points provided with the PenConfig
// draw_line_with_config draws a line between the points `x,y` and `x2,y2` using `PenConfig`.
pub fn (ctx &Context) draw_line_with_config(x f32, y f32, x2 f32, y2 f32, config PenConfig) {
if config.color.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand Down Expand Up @@ -119,10 +124,8 @@ pub fn (ctx &Context) draw_line_with_config(x f32, y f32, x2 f32, y2 f32, config
sgl.pop_matrix()
}

//---- polyline

// draw_empty_poly draws the borders of a polygon, given an array of points, and a color.
// Note that the points must be given in clockwise order.
// draw_poly_empty draws the outline of a polygon, given an array of points, and a color.
// NOTE that the points must be given in clockwise winding order.
pub fn (ctx &Context) draw_poly_empty(points []f32, c gx.Color) {
assert points.len % 2 == 0
len := points.len / 2
Expand All @@ -142,7 +145,8 @@ pub fn (ctx &Context) draw_poly_empty(points []f32, c gx.Color) {
}

// draw_convex_poly draws a convex polygon, given an array of points, and a color.
// Note that the points must be given in clockwise order.
// NOTE that the points must be given in clockwise winding order.
// The contents of the `points` array should be `x` and `y` coordinate pairs.
pub fn (ctx &Context) draw_convex_poly(points []f32, c gx.Color) {
assert points.len % 2 == 0
len := points.len / 2
Expand All @@ -168,8 +172,9 @@ pub fn (ctx &Context) draw_convex_poly(points []f32, c gx.Color) {
sgl.end()
}

//---- rectangle

// draw_rect_empty draws the outline of a rectangle.
// `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height and `c` is the color of the outline.
pub fn (ctx &Context) draw_rect_empty(x f32, y f32, w f32, h f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand All @@ -184,6 +189,9 @@ pub fn (ctx &Context) draw_rect_empty(x f32, y f32, w f32, h f32, c gx.Color) {
sgl.end()
}

// draw_rect_filled draws a filled rectangle.
// `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height and `c` is the color of the fill.
pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) {
$if macos {
if ctx.native_rendering {
Expand All @@ -204,6 +212,10 @@ pub fn (ctx &Context) draw_rect_filled(x f32, y f32, w f32, h f32, c gx.Color) {
}

// draw_rounded_rect_empty draws the outline of a rounded rectangle
// `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height.
// `radius` is the radius of the corner-rounding in pixels.
// `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) {
mut theta := f32(0)
mut xx := f32(0)
Expand Down Expand Up @@ -262,7 +274,11 @@ pub fn (ctx &Context) draw_rounded_rect_empty(x f32, y f32, w f32, h f32, radius
sgl.end()
}

// draw_rounded_rect_filled draws a filled rounded rectangle
// draw_rounded_rect_filled draws a filled rounded rectangle.
// `x`,`y` is the top-left corner of the rectangle.
// `w` is the width, `h` is the height .
// `radius` is the radius of the corner-rounding in pixels.
// `c` is the color of the outline.
pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radius f32, c gx.Color) {
sgl.c4b(c.r, c.g, c.b, c.a)
sgl.begin_triangle_strip()
Expand Down Expand Up @@ -331,8 +347,11 @@ pub fn (ctx &Context) draw_rounded_rect_filled(x f32, y f32, w f32, h f32, radiu
sgl.end()
}

//---- triangle

// draw_triangle_empty draws the outline of a triangle.
// `x`,`y` defines the first point
// `x2`,`y2` defines the second point
// `x3`,`y3` defines the third point
// `c` is the color of the outline.
pub fn (ctx &Context) draw_triangle_empty(x f32, y f32, x2 f32, y2 f32, x3 f32, y3 f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand All @@ -347,6 +366,11 @@ pub fn (ctx &Context) draw_triangle_empty(x f32, y f32, x2 f32, y2 f32, x3 f32,
sgl.end()
}

// draw_triangle_filled draws a filled triangle.
// `x`,`y` defines the first point
// `x2`,`y2` defines the second point
// `x3`,`y3` defines the third point
// `c` is the color of the outline.
pub fn (ctx &Context) draw_triangle_filled(x f32, y f32, x2 f32, y2 f32, x3 f32, y3 f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand All @@ -359,20 +383,24 @@ pub fn (ctx &Context) draw_triangle_filled(x f32, y f32, x2 f32, y2 f32, x3 f32,
sgl.end()
}

//---- square

// draw_square_empty draws the outline of a square.
// `x`,`y` is the top-left corner of the square.
// `s` is the length of each side of the square.
// `c` is the color of the outline.
[inline]
pub fn (ctx &Context) draw_square_empty(x f32, y f32, s f32, c gx.Color) {
ctx.draw_rect_empty(x, y, s, s, c)
}

// draw_square_filled draws a filled square.
// `x`,`y` is the top-left corner of the square.
// `s` is the length of each side of the square.
// `c` is the fill color.
[inline]
pub fn (ctx &Context) draw_square_filled(x f32, y f32, s f32, c gx.Color) {
ctx.draw_rect_filled(x, y, s, s, c)
}

//---- circle

// 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]!
Expand All @@ -389,7 +417,10 @@ fn radius_to_segments(r f32) int {
return int(math.ceil(2 * math.pi * r / 8))
}

// draw_circle_empty draws an empty circle
// draw_circle_empty draws the outline of a circle.
// `x`,`y` defines the center of the circle.
// `radius` defines the radius of the circle.
// `c` is the color of the outline.
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)
Expand All @@ -414,12 +445,19 @@ pub fn (ctx &Context) draw_circle_empty(x f32, y f32, radius f32, c gx.Color) {
sgl.end()
}

// draw_circle_filled draws a filled circle
// draw_circle_filled draws a filled circle.
// `x`,`y` defines the center of the circle.
// `radius` defines the radius of the circle.
// `c` is the fill color.
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)
// draw_circle_with_segments draws a filled circle with a specific number of segments.
// `x`,`y` defines the center of the circle.
// `radius` defines the radius of the circle.
// `segments` affects how smooth/round the circle is.
// `c` is the fill 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)
Expand All @@ -442,10 +480,16 @@ pub fn (ctx &Context) draw_circle_with_segments(x f32, y f32, radius f32, segmen
sgl.end()
}

pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) {
// draw_circle_line draws the outline of a circle with a specific number of segments.
// `x`,`y` defines the center of the circle.
// `radius` defines the radius of the circle.
// `segments` affects how smooth/round the circle is.
// `c` is the color of the outline.
pub fn (ctx &Context) draw_circle_line(x f32, y f32, radius 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 - radius + 1, ctx.height - (y + radius + 3), radius,
c)
return
}
}
Expand All @@ -455,7 +499,7 @@ pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.C
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)
Expand All @@ -469,8 +513,6 @@ pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.C
sgl.end()
}

//---- slice

// draw_slice_empty draws the outline of a circle slice/pie
pub fn (ctx &Context) draw_slice_empty(x f32, y f32, outer_radius f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
if c.a != 255 {
Expand Down Expand Up @@ -500,6 +542,12 @@ 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
// `x`,`y` defines the end point of the slice (center of the circle that the slice is part of).
// `radius` defines the radius ("length") of the slice.
// `start_angle` is the radians at which the slice starts.
// `end_angle` is the radians at which the slice ends.
// `segments` affects how smooth/round the slice is.
// `c` is the fill 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)
Expand All @@ -526,9 +574,14 @@ pub fn (ctx &Context) draw_slice_filled(x f32, y f32, radius f32, start_angle f3
sgl.end()
}

//---- arc

// draw_arc_empty draws the outline of an arc
// draw_arc_empty draws the outline of an arc.
// `x`,`y` defines the end point of the arc (center of the circle that the arc is part of).
// `inner_radius` defines the radius of the arc (length from the center point where the arc is drawn).
// `thickness` defines how wide the arc is drawn.
// `start_angle` is the radians at which the arc starts.
// `end_angle` is the radians at which the arc ends.
// `segments` affects how smooth/round the arc is.
// `c` is the color of the arc/outline.
pub fn (ctx &Context) draw_arc_empty(x f32, y f32, inner_radius f32, thickness f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
if start_angle == end_angle || inner_radius <= 0.0 {
return
Expand Down Expand Up @@ -584,7 +637,14 @@ pub fn (ctx &Context) draw_arc_empty(x f32, y f32, inner_radius f32, thickness f
sgl.end()
}

// draw_arc_filled draws a filled arc
// draw_arc_filled draws a filled arc.
// `x`,`y` defines the central point of the arc (center of the circle that the arc is part of).
// `inner_radius` defines the radius of the arc (length from the center point where the arc is drawn).
// `thickness` defines how wide the arc is drawn.
// `start_angle` is the radians at which the arc starts.
// `end_angle` is the radians at which the arc ends.
// `segments` affects how smooth/round the arc is.
// `c` is the fill color of the arc.
pub fn (ctx &Context) draw_arc_filled(x f32, y f32, inner_radius f32, thickness f32, start_angle f32, end_angle f32, segments int, c gx.Color) {
if start_angle == end_angle || inner_radius <= 0.0 {
return
Expand Down Expand Up @@ -623,9 +683,11 @@ pub fn (ctx &Context) draw_arc_filled(x f32, y f32, inner_radius f32, thickness
sgl.end()
}

//---- ellipse

// draw_ellipse_empty draws the outline of an ellipse, with a center at x,y
// draw_ellipse_empty draws the outline of an ellipse.
// `x`,`y` defines the center of the ellipse.
// `rw` defines the *width* radius of the ellipse.
// `rh` defines the *height* radius of the ellipse.
// `c` is the color of the outline.
pub fn (ctx &Context) draw_ellipse_empty(x f32, y f32, rw f32, rh f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand All @@ -641,7 +703,11 @@ pub fn (ctx &Context) draw_ellipse_empty(x f32, y f32, rw f32, rh f32, c gx.Colo
sgl.end()
}

// draw_ellipse_filled - draws an opaque elipse, with a center at x,y , filled with the color `c`
// draw_ellipse_filled draws an opaque elipse.
// `x`,`y` defines the center of the ellipse.
// `rw` defines the *width* radius of the ellipse.
// `rh` defines the *height* radius of the ellipse.
// `c` is the fill color.
pub fn (ctx &Context) draw_ellipse_filled(x f32, y f32, rw f32, rh f32, c gx.Color) {
if c.a != 255 {
sgl.load_pipeline(ctx.timage_pip)
Expand All @@ -658,8 +724,6 @@ pub fn (ctx &Context) draw_ellipse_filled(x f32, y f32, rw f32, rh f32, c gx.Col
sgl.end()
}

//---- bezier

// draw_cubic_bezier draws a cubic Bézier curve, also known as a spline, from four points.
// The four points is provided as one `points` array which contains a stream of point pairs (x and y coordinates).
// Thus a cubic Bézier could be declared as: `points := [x1, y1, control_x1, control_y1, control_x2, control_y2, x2, y2]`.
Expand Down

0 comments on commit aa9e2eb

Please sign in to comment.