Class: Ruby2D::Canvas
- Inherits:
-
Object
- Object
- Ruby2D::Canvas
- Includes:
- Renderable
- Defined in:
- lib/ruby2d/canvas.rb
Constant Summary
Constants included from Interactive
Interactive::OBJECT_EVENTS, Interactive::OBJECT_EVENT_FILTER_PREDICATES
Instance Attribute Summary collapse
-
#fill ⇒ Object
readonly
Returns the value of attribute fill.
-
#height ⇒ Object
Returns the value of attribute height.
-
#rotate ⇒ Object
Returns the value of attribute rotate.
-
#width ⇒ Object
Returns the value of attribute width.
-
#x ⇒ Object
Returns the value of attribute x.
-
#y ⇒ Object
Returns the value of attribute y.
Attributes included from Renderable
#color, #padding_bottom, #padding_left, #padding_right, #padding_top, #visible, #x_align, #y_align, #z
Instance Method Summary collapse
-
#_render_scene ⇒ Object
Scene-graph draw hook (see Renderable#_render_scene):
renderwith no overrides, minus its keyword handling — a zero-arg call into a keyword-heavyrenderstill pays microseconds of keyword setup on wasm mruby. -
#clear(fill_color = nil, color: nil, colour: nil, x: 0, y: 0, width: @width, height: @height) ⇒ Object
Clear the canvas, resetting all pixels to the fill color (or the given color).
-
#draw_image(image, x: 0, y: 0, width: nil, height: nil) ⇒ Object
Draw an Image onto this canvas at the given position and size.
-
#draw_line(x1: nil, y1: nil, x2: nil, y2: nil, points: nil, stroke_width: 1, dash: 0, gap: 5, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw a line.
-
#draw_lines(segments:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw many line segments with a single shared color and stroke width in one call.
-
#draw_polyline(points:, stroke_width: 1, color: nil, colour: nil, closed: false, opacity: nil) ⇒ Object
Draw a polyline from an array of [x, y] pairs.
-
#draw_text(text, x: 0, y: 0, width: nil, height: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw a Text onto this canvas at the given position and size, with optional color.
-
#fill_circle(x:, y:, radius:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a circle centered at (x,y) with the given radius.
-
#fill_ellipse(x:, y:, xradius:, yradius:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill an ellipse centered at (x,y) with the given x and y radii.
-
#fill_pixel_grid(cols:, rows:, cell_w:, cell_h:, colors:, x: 0, y: 0) ⇒ Object
Fill a regular grid of equal-size rectangles, each with its own color, in one call.
-
#fill_polygon(points:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a polygon defined by an array of [x, y] pairs.
-
#fill_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a quadrilateral.
-
#fill_rectangle(x:, y:, width:, height:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a rectangle at position (x,y) with the given width and height.
-
#fill_rectangles(rectangles:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill many rectangles with a single shared color in one call.
-
#fill_square(x:, y:, size:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a square at position (x,y) with the given size.
-
#fill_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a triangle.
-
#initialize(width:, height:, x: 0, y: 0, z: 0, rotate: 0, fill: [0, 0, 0, 0], tint: nil, opacity: nil, add: true, visible: true) ⇒ Canvas
constructor
Create a canvas with the given dimensions.
-
#opacity ⇒ Object
Get the tint's opacity.
- #opacity=(value) ⇒ Object
-
#render(x: nil, y: nil, width: nil, height: nil, rotate: nil, tint: nil, opacity: nil) ⇒ Object
Render the canvas.
-
#rx ⇒ Object
Get the rotation center x coordinate.
-
#rx=(val) ⇒ Object
Set the rotation center x coordinate.
-
#ry ⇒ Object
Get the rotation center y coordinate.
-
#ry=(val) ⇒ Object
Set the rotation center y coordinate.
-
#stroke_circle(x:, y:, radius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a circle outline centered at (x,y) with the given radius.
-
#stroke_ellipse(x:, y:, xradius:, yradius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke an ellipse outline centered at (x,y) with the given x and y radii.
-
#stroke_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a quadrilateral outline.
-
#stroke_rectangle(x:, y:, width:, height:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a rectangle outline at position (x,y) with the given width and height.
-
#stroke_square(x:, y:, size:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a square outline at position (x,y) with the given size.
-
#stroke_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a triangle outline.
-
#tint ⇒ Object
The canvas's tint color.
- #tint=(c) ⇒ Object
Methods included from Renderable
#_alignment_anchor_dx, #_alignment_anchor_dy, #_apply_padding, #_extract_alignment, #_point_in_polygon?, #_point_on_segment?, #_require_numeric_position, #_resolve_alignment, #_unrotate, #_validate_dimensions, #add, #colour=, #contains?, flatten_color, flatten_per_vertex, flatten_points, flatten_resolved_color, #hide, #padding=, #remove, resolve_color_or_default, resolve_single_color, #show
Methods included from Interactive
#_fire_event, #interactive?, #off, #on
Constructor Details
#initialize(width:, height:, x: 0, y: 0, z: 0, rotate: 0, fill: [0, 0, 0, 0], tint: nil, opacity: nil, add: true, visible: true) ⇒ Canvas
Create a canvas with the given dimensions
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/ruby2d/canvas.rb', line 17 def initialize(width:, height:, x: 0, y: 0, z: 0, rotate: 0, fill: [0, 0, 0, 0], tint: nil, opacity: nil, add: true, visible: true) self.x = x self.y = y @z = z @width = width @height = height @rotate = rotate @_user_rx = nil @_user_ry = nil @fill = Color.new(fill) self.tint = tint || 'white' self.opacity = opacity unless opacity.nil? @fill_r = @fill.r @fill_g = @fill.g @fill_b = @fill.b @fill_a = @fill.a Ext.canvas_create(self) @visible = visible self.add if add end |
Instance Attribute Details
#fill ⇒ Object (readonly)
Returns the value of attribute fill.
14 15 16 |
# File 'lib/ruby2d/canvas.rb', line 14 def fill @fill end |
#height ⇒ Object
Returns the value of attribute height.
13 14 15 |
# File 'lib/ruby2d/canvas.rb', line 13 def height @height end |
#rotate ⇒ Object
Returns the value of attribute rotate.
13 14 15 |
# File 'lib/ruby2d/canvas.rb', line 13 def rotate @rotate end |
#width ⇒ Object
Returns the value of attribute width.
13 14 15 |
# File 'lib/ruby2d/canvas.rb', line 13 def width @width end |
#x ⇒ Object
Returns the value of attribute x.
14 15 16 |
# File 'lib/ruby2d/canvas.rb', line 14 def x @x end |
#y ⇒ Object
Returns the value of attribute y.
14 15 16 |
# File 'lib/ruby2d/canvas.rb', line 14 def y @y end |
Instance Method Details
#_render_scene ⇒ Object
Scene-graph draw hook (see Renderable#_render_scene): render with no
overrides, minus its keyword handling — a zero-arg call into a
keyword-heavy render still pays microseconds of keyword setup on wasm
mruby.
518 519 520 |
# File 'lib/ruby2d/canvas.rb', line 518 def _render_scene Ext.canvas_draw(self, rx, ry) end |
#clear(fill_color = nil, color: nil, colour: nil, x: 0, y: 0, width: @width, height: @height) ⇒ Object
Clear the canvas, resetting all pixels to the fill color (or the given
color). The color may be passed positionally or via color:/colour:,
matching the rest of the draw API. Optionally clear only a rectangular
region.
466 467 468 469 470 471 |
# File 'lib/ruby2d/canvas.rb', line 466 def clear(fill_color = nil, color: nil, colour: nil, x: 0, y: 0, width: @width, height: @height) return unless validate4(:clear, x, y, width, height) input = fill_color || color || colour c = input ? Color.new(input) : @fill Ext.canvas_clear(self, [c.r, c.g, c.b, c.a, x, y, width, height]) end |
#draw_image(image, x: 0, y: 0, width: nil, height: nil) ⇒ Object
Draw an Image onto this canvas at the given position and size
445 446 447 448 449 450 |
# File 'lib/ruby2d/canvas.rb', line 445 def draw_image(image, x: 0, y: 0, width: nil, height: nil) w = width || image.width h = height || image.height return unless validate4(:draw_image, x, y, w, h) Ext.canvas_draw_image(self, image, [x, y, w, h]) end |
#draw_line(x1: nil, y1: nil, x2: nil, y2: nil, points: nil, stroke_width: 1, dash: 0, gap: 5, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw a line. Specify endpoints via points: or via numbered kwargs.
Pass dash: (and optionally gap:) to draw a dashed line. color:
accepts a single color or a Color::Set of 2 (start, end) for a
gradient along the length.
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/ruby2d/canvas.rb', line 364 def draw_line(x1: nil, y1: nil, x2: nil, y2: nil, points: nil, stroke_width: 1, dash: 0, gap: 5, color: nil, colour: nil, opacity: nil) if points validate_points(points, 2, :draw_line) x1, y1 = points[0] x2, y2 = points[1] end return unless validate_vertex4(:draw_line, x1, y1, x2, y2) opacity = clamp_opacity(opacity) if opacity c = resolve_color_or_set(color || colour) if c.is_a?(Color::Set) raise ArgumentError, 'Color::Set for draw_line must have 2 colors (start, end)' unless c.length == 2 Ext.canvas_draw_line_lerp(self, [ x1, y1, x2, y2, stroke_width, c[0].r, c[0].g, c[0].b, opacity || c[0].a, c[0].r, c[0].g, c[0].b, opacity || c[0].a, c[1].r, c[1].g, c[1].b, opacity || c[1].a, c[1].r, c[1].g, c[1].b, opacity || c[1].a, dash, gap ]) else # `c` is already a drawable Color (or the canvas tint); read it directly # instead of allocating a second Color via resolve_draw_color. Ext.canvas_draw_line(self, x1, y1, x2, y2, stroke_width, c.r, c.g, c.b, opacity || c.a, dash, gap) end end |
#draw_lines(segments:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw many line segments with a single shared color and stroke width in one call.
segments is an array of [[x, y], [x, y]] endpoint pairs.
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/ruby2d/canvas.rb', line 394 def draw_lines(segments:, stroke_width: 1, color: nil, colour: nil, opacity: nil) return if segments.empty? n = segments.length # Fused validate-and-build pass (`while`, not blocks) — per draw call # over N segments; see fill_rectangles. payload = [n] i = 0 while i < n s = segments[i] unless s.is_a?(Array) && s.length == 2 raise ArgumentError, 'segments must be an array of [[x, y], [x, y]] endpoint pairs' end a = s[0] b = s[1] unless a.is_a?(Array) && a.length == 2 && b.is_a?(Array) && b.length == 2 raise ArgumentError, 'segments must be an array of [[x, y], [x, y]] endpoint pairs' end payload.push(a[0], a[1], b[0], b[1]) i += 1 end opacity = clamp_opacity(opacity) if opacity c = resolve_draw_color(color || colour) payload.push(stroke_width, c.r, c.g, c.b, opacity || c.a) Ext.canvas_draw_lines(self, payload) end |
#draw_polyline(points:, stroke_width: 1, color: nil, colour: nil, closed: false, opacity: nil) ⇒ Object
Draw a polyline from an array of [x, y] pairs.
Set closed: true to connect the last point back to the first.
color: accepts a single color or a Color::Set of N (one per vertex)
interpolated along the path.
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/ruby2d/canvas.rb', line 425 def draw_polyline(points:, stroke_width: 1, color: nil, colour: nil, closed: false, opacity: nil) validate_point_pairs(points) n = points.length return if n < 2 return unless validate_pair_coords(points, :draw_polyline) colors = (color || colour, n, opacity, label: :draw_polyline) payload = [closed ? 1 : 0, n] i = 0 while i < n p = points[i] payload.push(p[0], p[1]) i += 1 end payload.push(stroke_width) payload.concat(colors) Ext.canvas_stroke_polyline(self, payload) end |
#draw_text(text, x: 0, y: 0, width: nil, height: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Draw a Text onto this canvas at the given position and size, with optional color
453 454 455 456 457 458 459 460 |
# File 'lib/ruby2d/canvas.rb', line 453 def draw_text(text, x: 0, y: 0, width: nil, height: nil, color: nil, colour: nil, opacity: nil) w = width || text.width h = height || text.height return unless validate4(:draw_text, x, y, w, h) opacity = clamp_opacity(opacity) if opacity c = resolve_draw_color(color || colour) Ext.canvas_draw_text(self, text, [x, y, w, h, c.r, c.g, c.b, opacity || c.a]) end |
#fill_circle(x:, y:, radius:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a circle centered at (x,y) with the given radius
238 239 240 |
# File 'lib/ruby2d/canvas.rb', line 238 def fill_circle(x:, y:, radius:, color: nil, colour: nil, opacity: nil) fill_ellipse(x: x, y: y, xradius: radius, yradius: radius, color: color, colour: colour, opacity: opacity) end |
#fill_ellipse(x:, y:, xradius:, yradius:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill an ellipse centered at (x,y) with the given x and y radii
243 244 245 246 247 248 249 250 251 |
# File 'lib/ruby2d/canvas.rb', line 243 def fill_ellipse(x:, y:, xradius:, yradius:, color: nil, colour: nil, opacity: nil) if opacity.is_a?(Array) raise ArgumentError, 'fill_ellipse/fill_circle is rasterized, not vertex-based, so it does not support a per-vertex opacity array' end return unless validate4(:fill_ellipse, x, y, xradius, yradius) opacity = clamp_opacity(opacity) if opacity c = resolve_draw_color(color || colour) Ext.canvas_fill_ellipse(self, x, y, xradius, yradius, c.r, c.g, c.b, opacity || c.a) end |
#fill_pixel_grid(cols:, rows:, cell_w:, cell_h:, colors:, x: 0, y: 0) ⇒ Object
Fill a regular grid of equal-size rectangles, each with its own color,
in one call. The cell at column c, row r covers
(x + c*cell_w, y + r*cell_h, cell_w, cell_h) and is colored by
colors[(r*cols + c)*4 .. +3]. colors is a flat array of
cols*rows*4 floats in 0..1: r0, g0, b0, a0, r1, g1, b1, a1, ....
Cells with alpha 0 are skipped. Designed for grid renderings
(fluid sims, heatmaps, tile fields) where per-rect FFI overhead
dominates over the actual pixel work.
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/ruby2d/canvas.rb', line 221 def fill_pixel_grid(cols:, rows:, cell_w:, cell_h:, colors:, x: 0, y: 0) return if cols < 1 || rows < 1 return unless validate4(:fill_pixel_grid, cell_w, cell_h, x, y) expected = cols * rows * 4 unless colors.length == expected raise ArgumentError, "colors must have #{expected} elements (cols*rows*4), got #{colors.length}" end Ext.canvas_fill_pixel_grid(self, [cols, rows, cell_w, cell_h, x, y], colors) end |
#fill_polygon(points:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a polygon defined by an array of [x, y] pairs. Concave polygons fill correctly: triangulation happens in C via ear clipping (R2D_TriangulatePolygon), shared with Polygon.new.
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/ruby2d/canvas.rb', line 256 def fill_polygon(points:, color: nil, colour: nil, opacity: nil) validate_point_pairs(points) n = points.length return if n < 3 return unless validate_pair_coords(points, :fill_polygon) opacity = clamp_opacity(opacity) if opacity c = resolve_color_or_set(color || colour) # `while` loops, not blocks — this is a per-draw-call path over N points # and block calls dominate on wasm mruby. if c.is_a?(Color::Set) || opacity.is_a?(Array) colors = per_vertex_fill_tuples(c, opacity, n, :fill_polygon) payload = [n] i = 0 while i < n p = points[i] col = colors[i] payload.push(p[0], p[1], col[0], col[1], col[2], col[3]) i += 1 end Ext.canvas_fill_polygon_lerp(self, payload) else payload = [n] i = 0 while i < n p = points[i] payload.push(p[0], p[1]) i += 1 end payload.push(c.r, c.g, c.b, opacity || c.a) Ext.canvas_fill_polygon(self, payload) end end |
#fill_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a quadrilateral. Specify vertices via points: or via numbered kwargs.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ruby2d/canvas.rb', line 119 def fill_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, color: nil, colour: nil, opacity: nil) if points validate_points(points, 4, :fill_quad) x1, y1 = points[0] x2, y2 = points[1] x3, y3 = points[2] x4, y4 = points[3] end return unless validate_vertex8(:fill_quad, x1, y1, x2, y2, x3, y3, x4, y4) opacity = clamp_opacity(opacity) if opacity c = resolve_color_or_set(color || colour) if c.is_a?(Color::Set) || opacity.is_a?(Array) colors = per_vertex_fill_tuples(c, opacity, 4, :fill_quad) # Split into triangles (0,1,2) and (0,2,3), each carrying its vertices' # colors so the per-vertex gradient interpolates across the quad. Ext.canvas_fill_triangle_lerp(self, [x1, y1, *colors[0], x2, y2, *colors[1], x3, y3, *colors[2]]) Ext.canvas_fill_triangle_lerp(self, [x1, y1, *colors[0], x3, y3, *colors[2], x4, y4, *colors[3]]) else a = opacity || c.a Ext.canvas_fill_triangle(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, a) Ext.canvas_fill_triangle(self, x1, y1, x3, y3, x4, y4, c.r, c.g, c.b, a) end end |
#fill_rectangle(x:, y:, width:, height:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a rectangle at position (x,y) with the given width and height
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/ruby2d/canvas.rb', line 147 def fill_rectangle(x:, y:, width:, height:, color: nil, colour: nil, opacity: nil) return unless validate4(:fill_rectangle, x, y, width, height) opacity = clamp_opacity(opacity) if opacity c = resolve_color_or_set(color || colour) # Per-vertex (corner) coloring or opacity needs the quad path; a single # flat color uses the dedicated rectangle rasterizer. if c.is_a?(Color::Set) || opacity.is_a?(Array) fill_quad( x1: x, y1: y, x2: x + width, y2: y, x3: x + width, y3: y + height, x4: x, y4: y + height, color: c, opacity: opacity ) else # `c` is already a drawable Color (or the canvas tint) from # resolve_color_or_set; read it directly instead of allocating a second # Color via resolve_draw_color. Ext.canvas_fill_rectangle(self, x, y, width, height, c.r, c.g, c.b, opacity || c.a) end end |
#fill_rectangles(rectangles:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill many rectangles with a single shared color in one call.
rectangles is an array of [x, y, width, height] tuples.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/ruby2d/canvas.rb', line 169 def fill_rectangles(rectangles:, color: nil, colour: nil, opacity: nil) return if rectangles.empty? if opacity.is_a?(Array) raise ArgumentError, 'fill_rectangles uses a single shared color and does not support a per-vertex opacity array' end opacity = clamp_opacity(opacity) if opacity # One fused validate-and-build pass (`while`, not blocks — this runs per # draw call on N tuples, and block calls dominate on wasm mruby). A # malformed tuple or non-Numeric coordinate is a programming mistake — # raise, as the vertex-based methods do. A rect carrying a non-finite # (NaN/Inf) coordinate or size is instead dropped rather than forwarded # to C; the finite-only payload keeps the draw a clean no-op for the bad # rects while still drawing the good ones. payload = [0] count = 0 i = 0 size = rectangles.size while i < size r = rectangles[i] unless r.is_a?(Array) && r.length == 4 raise ArgumentError, 'rectangles must be an array of [x, y, width, height] tuples' end x = r[0] y = r[1] w = r[2] h = r[3] unless x.is_a?(Numeric) && y.is_a?(Numeric) && w.is_a?(Numeric) && h.is_a?(Numeric) raise ArgumentError, 'fill_rectangles: every coordinate must be a number' end if finite4?(x, y, w, h) count += 1 payload.push(x, y, w, h) end i += 1 end return if count.zero? payload[0] = count c = resolve_draw_color(color || colour) payload.push(c.r, c.g, c.b, opacity || c.a) Ext.canvas_fill_rectangles(self, payload) end |
#fill_square(x:, y:, size:, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a square at position (x,y) with the given size
233 234 235 |
# File 'lib/ruby2d/canvas.rb', line 233 def fill_square(x:, y:, size:, color: nil, colour: nil, opacity: nil) fill_rectangle(x: x, y: y, width: size, height: size, color: color, colour: colour, opacity: opacity) end |
#fill_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, color: nil, colour: nil, opacity: nil) ⇒ Object
Fill a triangle. Specify vertices via points: or via numbered kwargs.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ruby2d/canvas.rb', line 95 def fill_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, color: nil, colour: nil, opacity: nil) if points validate_points(points, 3, :fill_triangle) x1, y1 = points[0] x2, y2 = points[1] x3, y3 = points[2] end return unless validate_vertex6(:fill_triangle, x1, y1, x2, y2, x3, y3) opacity = clamp_opacity(opacity) if opacity c = resolve_color_or_set(color || colour) # A single flat color reads its channels straight into the C call; only # a `Color::Set` or per-vertex opacity array builds the tuple array. if c.is_a?(Color::Set) || opacity.is_a?(Array) colors = per_vertex_fill_tuples(c, opacity, 3, :fill_triangle) Ext.canvas_fill_triangle_lerp(self, [x1, y1, *colors[0], x2, y2, *colors[1], x3, y3, *colors[2]]) else Ext.canvas_fill_triangle(self, x1, y1, x2, y2, x3, y3, c.r, c.g, c.b, opacity || c.a) end end |
#opacity ⇒ Object
Get the tint's opacity. Canvas overrides Renderable#opacity because its
modulating color is @tint, not @color.
54 55 56 |
# File 'lib/ruby2d/canvas.rb', line 54 def opacity @tint&.opacity end |
#opacity=(value) ⇒ Object
58 59 60 |
# File 'lib/ruby2d/canvas.rb', line 58 def opacity=(value) @tint.opacity = value end |
#render(x: nil, y: nil, width: nil, height: nil, rotate: nil, tint: nil, opacity: nil) ⇒ Object
Render the canvas. Called with overrides for one-shot rendering inside a
render block; with no arguments it draws the same frame the scene graph
does (delegating to _render_scene). width:/height: scale the
displayed output — the underlying pixel buffer is fixed at construction.
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/ruby2d/canvas.rb', line 477 def render(x: nil, y: nil, width: nil, height: nil, rotate: nil, tint: nil, opacity: nil) if x.nil? && y.nil? && width.nil? && height.nil? && rotate.nil? && tint.nil? && opacity.nil? return _render_scene end Window.render_ready_check saved_x, saved_y = @x, @y saved_width, saved_height = @width, @height saved_rotate = @rotate saved_tint = @tint @x = x if x @y = y if y @width = width if width @height = height if height @rotate = rotate if rotate if tint || opacity @tint = tint ? Color.new(tint) : Color.new(saved_tint) @tint.opacity = opacity if opacity end begin Ext.canvas_draw(self, rx, ry) ensure @x, @y = saved_x, saved_y @width, @height = saved_width, saved_height @rotate = saved_rotate @tint = saved_tint end end |
#rx ⇒ Object
Get the rotation center x coordinate
75 76 77 |
# File 'lib/ruby2d/canvas.rb', line 75 def rx @_user_rx.nil? ? @x + @width / 2.0 : @_user_rx end |
#rx=(val) ⇒ Object
Set the rotation center x coordinate
85 86 87 |
# File 'lib/ruby2d/canvas.rb', line 85 def rx=(val) @_user_rx = val end |
#ry ⇒ Object
Get the rotation center y coordinate
80 81 82 |
# File 'lib/ruby2d/canvas.rb', line 80 def ry @_user_ry.nil? ? @y + @height / 2.0 : @_user_ry end |
#ry=(val) ⇒ Object
Set the rotation center y coordinate
90 91 92 |
# File 'lib/ruby2d/canvas.rb', line 90 def ry=(val) @_user_ry = val end |
#stroke_circle(x:, y:, radius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a circle outline centered at (x,y) with the given radius. Single color only — sectors have no natural vertex identity.
339 340 341 342 |
# File 'lib/ruby2d/canvas.rb', line 339 def stroke_circle(x:, y:, radius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) stroke_ellipse(x: x, y: y, xradius: radius, yradius: radius, sectors: sectors, stroke_width: stroke_width, color: color, colour: colour, opacity: opacity) end |
#stroke_ellipse(x:, y:, xradius:, yradius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke an ellipse outline centered at (x,y) with the given x and y radii. Single color only — sectors have no natural vertex identity.
346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/ruby2d/canvas.rb', line 346 def stroke_ellipse(x:, y:, xradius:, yradius:, sectors: 30, stroke_width: 1, color: nil, colour: nil, opacity: nil) c = resolve_draw_color(color || colour) a = (clamp_opacity(opacity) if opacity) || c.a verts = [] colors = [] sectors.times do |i| angle = 2.0 * Math::PI * i / sectors verts << x + xradius * Math.cos(angle) verts << y + yradius * Math.sin(angle) colors << c.r << c.g << c.b << a end Ext.canvas_stroke_polygon(self, [sectors, *verts, stroke_width, *colors]) end |
#stroke_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a quadrilateral outline. Specify vertices via points: or via
numbered kwargs. color: accepts a single color or a Color::Set of 4
(one per vertex) interpolated around the perimeter.
309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'lib/ruby2d/canvas.rb', line 309 def stroke_quad(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, x4: nil, y4: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) if points validate_points(points, 4, :stroke_quad) x1, y1 = points[0] x2, y2 = points[1] x3, y3 = points[2] x4, y4 = points[3] end return unless validate_vertex8(:stroke_quad, x1, y1, x2, y2, x3, y3, x4, y4) colors = (color || colour, 4, opacity, label: :stroke_quad) Ext.canvas_stroke_polygon(self, [4, x1, y1, x2, y2, x3, y3, x4, y4, stroke_width, *colors]) end |
#stroke_rectangle(x:, y:, width:, height:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a rectangle outline at position (x,y) with the given width and height
324 325 326 327 328 329 330 |
# File 'lib/ruby2d/canvas.rb', line 324 def stroke_rectangle(x:, y:, width:, height:, stroke_width: 1, color: nil, colour: nil, opacity: nil) stroke_quad( x1: x, y1: y, x2: x + width, y2: y, x3: x + width, y3: y + height, x4: x, y4: y + height, stroke_width: stroke_width, color: color, colour: colour, opacity: opacity ) end |
#stroke_square(x:, y:, size:, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a square outline at position (x,y) with the given size
333 334 335 |
# File 'lib/ruby2d/canvas.rb', line 333 def stroke_square(x:, y:, size:, stroke_width: 1, color: nil, colour: nil, opacity: nil) stroke_rectangle(x: x, y: y, width: size, height: size, stroke_width: stroke_width, color: color, colour: colour, opacity: opacity) end |
#stroke_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) ⇒ Object
Stroke a triangle outline. Specify vertices via points: or via numbered
kwargs. color: accepts a single color or a Color::Set of 3 (one per
vertex) interpolated around the perimeter.
293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/ruby2d/canvas.rb', line 293 def stroke_triangle(x1: nil, y1: nil, x2: nil, y2: nil, x3: nil, y3: nil, points: nil, stroke_width: 1, color: nil, colour: nil, opacity: nil) if points validate_points(points, 3, :stroke_triangle) x1, y1 = points[0] x2, y2 = points[1] x3, y3 = points[2] end return unless validate_vertex6(:stroke_triangle, x1, y1, x2, y2, x3, y3) colors = (color || colour, 3, opacity, label: :stroke_triangle) Ext.canvas_stroke_polygon(self, [3, x1, y1, x2, y2, x3, y3, stroke_width, *colors]) end |
#tint ⇒ Object
The canvas's tint color. The canvas's own pixel buffer is multiplied by
this — tint: 'red' makes the canvas redder, not solid red.
44 45 46 |
# File 'lib/ruby2d/canvas.rb', line 44 def tint @tint end |