Class: QrForge::Layout

Inherits:
Object
  • Object
show all
Defined in:
lib/qr_forge/layout.rb

Overview

Responsible only for computing all the exclusion & pattern zones

Constant Summary collapse

FINDER_PATTERN_SIZE =
7
ALIGNMENT_PATTERN_SIZE =
5

Instance Method Summary collapse

Constructor Details

#initialize(qr_data:, has_image: false) ⇒ Layout



9
10
11
12
13
14
15
16
17
# File 'lib/qr_forge/layout.rb', line 9

def initialize(qr_data:, has_image: false)
  @qr_data = qr_data
  @module_count = qr_data.module_count
  @version = qr_data.version
  @modules = qr_data.modules
  @has_image = has_image

  # build_cache
end

Instance Method Details

#alignment_patternsHash

TODO: Remove some complexity out of this method Returns the alignment patterns’ coordinates and areas. Coordinates are the top-left corners of the alignment patterns. Areas are the ranges of rows and columns that the alignment patterns cover.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/qr_forge/layout.rb', line 83

def alignment_patterns
  @alignment_patterns ||= begin
    # Offset from center to top-left corner of the alignment pattern
    half_offset = (ALIGNMENT_PATTERN_SIZE - 1) / 2

    # RQRCodeCore provides a helper method to get the alignment pattern centers
    alignment_center_coordinates = RQRCodeCore::QRUtil.get_pattern_positions(@version)

    # Filter out centers that are inside finder patterns or the image area
    valid_alignment_coordinates = alignment_center_coordinates.product(alignment_center_coordinates).reject do |center_row, center_col|
      inside_finder?(center_row, center_col) || (@has_image && inside_image?(center_row, center_col))
    end

    locations = { coordinates: [], areas: [] }

    # Map valid alignment centers to their top-left corners and areas
    valid_alignment_coordinates.map do |center_row, center_col|
      top_left_row = center_row - half_offset
      top_left_col = center_col - half_offset

      locations[:coordinates] << [top_left_row, top_left_col]

      row_range = top_left_row...(top_left_row + ALIGNMENT_PATTERN_SIZE)
      col_range = top_left_col...(top_left_col + ALIGNMENT_PATTERN_SIZE)

      locations[:areas] << [row_range, col_range]
    end

    locations
  end
end

#finder_patternsHash

Returns the finder patterns’ coordinates and areas. Coordinates are the top-left corners of the finder patterns. Areas are the ranges of rows and columns that the finder patterns cover.



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/qr_forge/layout.rb', line 64

def finder_patterns
  @finder_patterns ||= begin
    offset = @module_count - FINDER_PATTERN_SIZE
    coordinates = [[0, 0], [0, offset], [offset, 0]]
    areas = []

    coordinates.map do |row, col|
      areas << [(row...(row + FINDER_PATTERN_SIZE)), (col...(col + FINDER_PATTERN_SIZE))]
    end

    { coordinates: coordinates, areas: areas }
  end
end

#image_areaRange

Returns the image area as a Range of rows and columns. The image area is centered in the QR code and its size is based on the module count.



50
51
52
53
54
55
56
57
# File 'lib/qr_forge/layout.rb', line 50

def image_area
  @image_area ||= begin
    raw  = (@module_count * 0.30).round
    size = raw.even? ? raw + 1 : raw
    start_idx = ((@module_count - size) / 2.0).floor
    (start_idx...(start_idx + size))
  end
end

#inside_alignment?(row, col) ⇒ Boolean

Checks if a given row and column are inside the alignment patterns.



42
43
44
# File 'lib/qr_forge/layout.rb', line 42

def inside_alignment?(row, col)
  inside_area?(row, col, alignment_patterns[:areas])
end

#inside_finder?(row, col) ⇒ Boolean

Checks if a given row and column are inside the finder patterns.



33
34
35
# File 'lib/qr_forge/layout.rb', line 33

def inside_finder?(row, col)
  inside_area?(row, col, finder_patterns[:areas])
end

#inside_image?(row, col) ⇒ Boolean

Checks if a given row and column are inside the image area.



24
25
26
# File 'lib/qr_forge/layout.rb', line 24

def inside_image?(row, col)
  inside_area?(row, col, image_area)
end