class Spitewaste::ImageEmitter
Constants
- DEFAULTS
- INSN_GROUPS
- LINEFEED
- SCHEMES
Private Class Methods
parse_color(color)
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 127 def self.parse_color color case color when Integer color << 8 | 255 else Integer(color) << 8 | 255 end end
Public Instance Methods
emit(io: io.write generate_image)
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 16 def emit io: io.write generate_image end
Private Instance Methods
color_for(token, type)
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 120 def color_for token, type colors = @palette[token == ?\t ? :normal : :bright] type = :number if type.is_a? Integer type = INSN_GROUPS[type] unless @palette[type] colors[@palette[type]] end
generate_image()
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 22 def generate_image @options = DEFAULTS.merge options line, padding, margin = @options.values_at :line_height, :padding, :margin height = @options[:cell_size] width = height / 2 img, rects = generate_rects linefeeds = @palette[:bright].values.map { |c| lf = LINEFEED # no need to dup; modify in-place then store resampled lf.pixels.map! { |p| p == 0 ? 0 : c } [c, lf.resample_bilinear(height, height / 2)] }.to_h rects.each do |x, y, x2, color| if x2 # space or tab img.rect x * width + margin, y * line + margin, x2 * width + margin - padding - 1, y * line + height + margin - padding - 1, color, color else # draw fancy linefeed img.compose! linefeeds[color], x * width + margin + padding, y * line + margin + height / 4 end end img end
generate_palette()
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 97 def generate_palette scheme = @options[:colors] palette = SCHEMES[scheme] palette ||= if File.exists?(scheme) YAML.load_file(scheme)['colors'] else warn "can't load colorscheme #{scheme}; " + "falling back to gruvbox_dark" SCHEMES['gruvbox_dark'] end {stack: 'blue', flow: 'red', math: 'green', heap: 'yellow', io: 'yellow', calls: 'cyan', number: 'magenta'}.merge palette end
generate_rects()
click to toggle source
# File lib/spitewaste/emitters/image.rb, line 52 def generate_rects # We need two representations of the program: # - stream of ops/args to determine how to emit (colors, etc.) # - Whitespace tokens (what to emit) # We know `instructions` to be a valid instance of the first, so we just # convert those to get the second rather than doing another parse + emit. stream = instructions.flatten.compact chunks = stream.map { |token| OPERATORS_M2T[token] || WhitespaceEmitter.encode(token) } # Determine the size of the output image. tw = @options[:tab_width] lines = chunks.join.lines rows = lines.size cols = lines.map { |line| line.size + tw.pred * line.count(?\t) + line.count(?\n) }.max width = cols * @options[:cell_size] / 2 + @options[:margin] * 2 height = rows * @options[:line_height] + @options[:margin] * 2 # Map palette colors to 32-bit values for ChunkyPNG. @palette = generate_palette.transform_keys &:to_sym %i[normal bright].each { |style| @palette[style].transform_values!(&ImageEmitter.method(:parse_color)) } img = ChunkyPNG::Image.new width, height, @palette[:primary]['background'] x = y = 0 rects = chunks.zip(stream).flat_map { |tokens, type| tokens.chars.map { |token| cx, cy = x, y nx = case token when ' ' ; x += 1 ; cx + 1 when ?\t ; x += tw ; cx + tw when ?\n ; x, y = 0, y + 1 ; nil end [cx, cy, nx, color_for(token, type)] } } [img, rects] end