Class: Vizcore::Renderer::SnapshotRenderer::Canvas

Inherits:
Object
  • Object
show all
Defined in:
lib/vizcore/renderer/snapshot_renderer.rb

Overview

Tiny RGBA canvas with alpha blending and a few primitive drawing helpers.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width:, height:) ⇒ Canvas

Returns a new instance of Canvas.



811
812
813
814
815
816
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 811

def initialize(width:, height:)
  @width = width
  @height = height
  @bytes = String.new(capacity: width * height * 4, encoding: Encoding::BINARY)
  @bytes << ([0, 0, 0, 255].pack("C4") * (width * height))
end

Instance Attribute Details

#bytesObject (readonly)

Returns the value of attribute bytes.



818
819
820
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 818

def bytes
  @bytes
end

#heightObject (readonly)

Returns the value of attribute height.



818
819
820
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 818

def height
  @height
end

#widthObject (readonly)

Returns the value of attribute width.



818
819
820
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 818

def width
  @width
end

Instance Method Details

#draw_circle_outline(cx, cy, radius, color, alpha:) ⇒ Object



845
846
847
848
849
850
851
852
853
854
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 845

def draw_circle_outline(cx, cy, radius, color, alpha:)
  segments = 96
  previous = nil
  (0..segments).each do |index|
    angle = (index.to_f / segments) * Math::PI * 2
    point = [cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius]
    draw_line(previous[0], previous[1], point[0], point[1], color, alpha: alpha) if previous
    previous = point
  end
end

#draw_label(text, x:, y:, color:, alpha:, letter_spacing: 0.0) ⇒ Object



893
894
895
896
897
898
899
900
901
902
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 893

def draw_label(text, x:, y:, color:, alpha:, letter_spacing: 0.0)
  chars = text.each_byte.first(24)
  char_width = 14 + Float(letter_spacing).clamp(0.0, 96.0).round
  total_width = chars.length * char_width
  start_x = x.round - total_width / 2
  chars.each_with_index do |byte, index|
    height_factor = 0.35 + (byte % 9) * 0.07
    fill_bar(start_x + index * char_width, y.round, 9, (42 * height_factor).round, color, alpha)
  end
end

#draw_line(x1, y1, x2, y2, color, alpha:) ⇒ Object



866
867
868
869
870
871
872
873
874
875
876
877
878
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 866

def draw_line(x1, y1, x2, y2, color, alpha:)
  x1 = x1.round
  y1 = y1.round
  x2 = x2.round
  y2 = y2.round
  steps = [(x2 - x1).abs, (y2 - y1).abs].max
  return blend_pixel(x1, y1, color, alpha) if steps.zero?

  steps.times do |step|
    t = step.to_f / steps
    blend_pixel(interpolate(x1, x2, t).round, interpolate(y1, y2, t).round, color, alpha)
  end
end

#draw_rect_outline(x, y, rect_width, rect_height, color, alpha:) ⇒ Object



838
839
840
841
842
843
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 838

def draw_rect_outline(x, y, rect_width, rect_height, color, alpha:)
  draw_line(x, y, x + rect_width, y, color, alpha: alpha)
  draw_line(x + rect_width, y, x + rect_width, y + rect_height, color, alpha: alpha)
  draw_line(x + rect_width, y + rect_height, x, y + rect_height, color, alpha: alpha)
  draw_line(x, y + rect_height, x, y, color, alpha: alpha)
end

#draw_wave(y_base, amplitude:, color:, alpha:, height_scale: 1.0) ⇒ Object



828
829
830
831
832
833
834
835
836
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 828

def draw_wave(y_base, amplitude:, color:, alpha:, height_scale: 1.0)
  previous = nil
  width.times do |x|
    phase = (x.to_f / width) * Math::PI * 4.0
    y = y_base + Math.sin(phase) * height * (0.06 + amplitude * 0.08) * height_scale
    draw_line(previous[0], previous[1], x, y, color, alpha: alpha) if previous
    previous = [x, y]
  end
end

#fill_circle(cx, cy, radius, color, alpha:) ⇒ Object



880
881
882
883
884
885
886
887
888
889
890
891
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 880

def fill_circle(cx, cy, radius, color, alpha:)
  cx = cx.round
  cy = cy.round
  radius = radius.round
  (cy - radius).upto(cy + radius) do |y|
    (cx - radius).upto(cx + radius) do |x|
      next if ((x - cx)**2) + ((y - cy)**2) > radius**2

      blend_pixel(x, y, color, alpha)
    end
  end
end

#fill_gradient(top, bottom) ⇒ Object



820
821
822
823
824
825
826
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 820

def fill_gradient(top, bottom)
  height.times do |y|
    t = y.to_f / [height - 1, 1].max
    color = 3.times.map { |index| interpolate(top[index], bottom[index], t).round }
    width.times { |x| set_pixel(x, y, color, 255) }
  end
end

#fill_rect(x, y, rect_width, rect_height, color, alpha:) ⇒ Object



856
857
858
859
860
861
862
863
864
# File 'lib/vizcore/renderer/snapshot_renderer.rb', line 856

def fill_rect(x, y, rect_width, rect_height, color, alpha:)
  start_x = x.round
  end_x = (x + rect_width).round
  start_y = y.round
  end_y = (y + rect_height).round
  start_y.upto(end_y) do |py|
    start_x.upto(end_x) { |px| blend_pixel(px, py, color, alpha) }
  end
end