class RQRCode::Export::SVG::Path
def build(module_size, options = {})
def build(module_size, options = {}) # Extract values from options color = options[:color] offset_x = options[:offset_x].to_i offset_y = options[:offset_y].to_i # Prefix hexadecimal colors unless using a named color (symbol) color = "##{color}" unless color.is_a?(Symbol) modules_array = @qrcode.modules matrix_width = matrix_height = modules_array.length + 1 empty_row = [Array.new(matrix_width - 1, false)] edge_matrix = Array.new(matrix_height) { Array.new(matrix_width) } (empty_row + modules_array + empty_row).each_cons(2).with_index do |row_pair, row_index| first_row, second_row = row_pair # horizontal edges first_row.zip(second_row).each_with_index do |cell_pair, column_index| edge = case cell_pair when [true, false] then Edge.new column_index + 1, row_index, :left when [false, true] then Edge.new column_index, row_index, :right end (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge end # vertical edges ([false] + second_row + [false]).each_cons(2).each_with_index do |cell_pair, column_index| edge = case cell_pair when [true, false] then Edge.new column_index, row_index, :down when [false, true] then Edge.new column_index, row_index + 1, :up end (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge end end edge_count = edge_matrix.flatten.compact.count path = [] while edge_count > 0 edge_loop = [] next_matrix_cell = edge_matrix.find(&:any?).find { |cell| cell&.any? } edge = next_matrix_cell.first while edge edge_loop << edge matrix_cell = edge_matrix[edge.start_y][edge.start_x] matrix_cell.delete edge edge_matrix[edge.start_y][edge.start_x] = nil if matrix_cell.empty? edge_count -= 1 # try to find an edge continuing the current edge edge = edge_matrix[edge.end_y][edge.end_x]&.first end first_edge = edge_loop.first edge_loop_string = SVG_PATH_COMMANDS[:move] edge_loop_string += "#{first_edge.start_x} #{first_edge.start_y}" edge_loop.chunk(&:direction).to_a[0...-1].each do |direction, edges| edge_loop_string << "#{SVG_PATH_COMMANDS[direction]}#{edges.length}" end edge_loop_string << SVG_PATH_COMMANDS[:close] path << edge_loop_string end @result << %{<path d="#{path.join}" fill="#{color}" transform="translate(#{offset_x},#{offset_y}) scale(#{module_size})"/>} end