Skip to content

Commit 9ddd471

Browse files
committed
[qr] Fix various bugs
1 parent 3873aba commit 9ddd471

File tree

4 files changed

+87
-61
lines changed

4 files changed

+87
-61
lines changed

addons/qr_code/plugin.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
name="QR Code"
44
description="QR Code generator."
55
author="Iceflower S"
6-
version="1.3.0"
6+
version="1.3.1"
77
script="plugin.gd"
88
license="MIT"
99
repository="https://github.com/kenyoni-software/godot-addons"

addons/qr_code/qr_code.gd

Lines changed: 81 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,9 @@ const _ALIGNMENT_PATTERN_POSITIONS: Array[Array] = [
681681
## remainder bits after structured data bits
682682
const _REMAINDER_BITS: Array[int] = [0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0]
683683

684+
const _DARK: int = 1
685+
const _LIGHT: int = 0
686+
684687
static var _number_rx: RegEx = RegEx.create_from_string("[^\\d]*")
685688
static var _alphanumeric_rx: RegEx = RegEx.create_from_string("[^0-9A-Z $%*+\\-.\\/:]*")
686689

@@ -754,6 +757,8 @@ func set_use_eci(new_use_eci: bool) -> void:
754757
func set_eci_value(new_eci_value: int) -> void:
755758
if new_eci_value == eci_value:
756759
return
760+
if !ECI.values().has(new_eci_value):
761+
return
757762
eci_value = new_eci_value
758763
self._clear_cache()
759764

@@ -783,10 +788,18 @@ func get_module_count() -> int:
783788
func calc_min_version() -> int:
784789
var input_size: int = self._get_input_data_size()
785790
for idx: int in range(_DATA_CAPACITY.size()):
786-
var cap: int = _DATA_CAPACITY[idx][self.error_correction][self.mode]
787-
if self.eci_value != ECI.ISO_8859_1:
791+
var cap: int = _DATA_CAPACITY[idx][ self.error_correction][ self.mode]
792+
if self.use_eci:
788793
# subtract roughly eci header size
789-
cap -= 4
794+
match self.mode:
795+
Mode.NUMERIC:
796+
cap -= 4
797+
Mode.ALPHANUMERIC:
798+
cap -= 3
799+
Mode.BYTE:
800+
cap -= 2
801+
Mode.KANJI:
802+
cap -= 1
790803
if input_size <= cap:
791804
return idx + 1
792805
return -1
@@ -809,7 +822,7 @@ static func _mask_pattern_fns() -> Array[Callable]:
809822

810823
# helper function check if a bit is set
811824
static func _get_state(value: int, idx: int) -> bool:
812-
return (value & (1 << idx))
825+
return value & (1 << idx) != 0
813826

814827
func _get_data_codeword_count() -> int:
815828
return _ERROR_CORRECTION[self.version - 1][self.error_correction][0]
@@ -832,9 +845,9 @@ func _get_alignment_pattern_positions() -> Array[Vector2i]:
832845
for row: int in _ALIGNMENT_PATTERN_POSITIONS[self.version - 1]:
833846
for col: int in _ALIGNMENT_PATTERN_POSITIONS[self.version - 1]:
834847
# do not overlap finder positions
835-
if row - 2 < 8 && col - 2 < 8 || \
836-
row > module_count - 8 && col - 2 < 8 || \
837-
row - 2 < 8 && col > module_count - 8:
848+
if (row - 2 < 8 && col - 2 < 8) || \
849+
(row - 2 < 8 && col + 2 > module_count - 8) || \
850+
(row + 2 >= module_count - 8 && col - 2 < 8):
838851
continue
839852
positions.append(Vector2i(row, col))
840853
return positions
@@ -915,9 +928,9 @@ func generate_image(module_px_size: int = 1, light_module_color: Color = Color.W
915928
for x: int in range(module_count):
916929
var color: Color = Color.PINK
917930
match qr_code[x + y * module_count]:
918-
0:
931+
_LIGHT:
919932
color = light_module_color
920-
1:
933+
_DARK:
921934
color = dark_module_color
922935
for offset_x: int in range(module_px_size):
923936
for offset_y: int in range(module_px_size):
@@ -947,6 +960,7 @@ func put_kanji(data: String) -> void:
947960
if self.mode != Mode.KANJI || data != self._input_data:
948961
self._clear_cache()
949962
self.mode = Mode.KANJI
963+
# clear invalid characters
950964
self._input_data = ShiftJIS.get_string_from_shift_jis_2004(ShiftJIS.to_shift_jis_2004_buffer(data))
951965

952966
## returns row by row
@@ -1153,62 +1167,70 @@ func _structure_data(data_stream: BitStream, err_correction: Array[PackedByteArr
11531167
static func _place_finder(data: PackedByteArray, module_count: int, pos: Vector2i) -> void:
11541168
for row: int in range(7):
11551169
for col: int in range(7):
1156-
data[(pos.x + row) + (pos.y + col) * module_count] = 1
1170+
data[(pos.x + row) + (pos.y + col) * module_count] = _DARK
11571171
for idx: int in range(5):
1158-
data[(pos.x + 1 + idx) + (pos.y + 1) * module_count] = 0
1159-
data[(pos.x + 1 + idx) + (pos.y + 5) * module_count] = 0
1172+
data[(pos.x + 1 + idx) + (pos.y + 1) * module_count] = _LIGHT
1173+
data[(pos.x + 1 + idx) + (pos.y + 5) * module_count] = _LIGHT
11601174
for idx: int in range(3):
1161-
data[(pos.x + 1) + (pos.y + 2 + idx) * module_count] = 0
1162-
data[(pos.x + 5) + (pos.y + 2 + idx) * module_count] = 0
1175+
data[(pos.x + 1) + (pos.y + 2 + idx) * module_count] = _LIGHT
1176+
data[(pos.x + 5) + (pos.y + 2 + idx) * module_count] = _LIGHT
11631177

11641178
# pos is center
11651179
# 5 x 5 size
11661180
static func _place_align_pattern(data: PackedByteArray, module_count: int, pos: Vector2i) -> void:
11671181
for row: int in range(5):
11681182
for col: int in range(5):
1169-
data[(pos.x - 2 + row) + (pos.y - 2 + col) * module_count] = 1
1183+
data[(pos.x - 2 + row) + (pos.y - 2 + col) * module_count] = _DARK
11701184
for idx: int in range(3):
1171-
data[(pos.x - 1 + idx) + (pos.y - 1) * module_count] = 0
1172-
data[(pos.x - 1 + idx) + (pos.y + 1) * module_count] = 0
1173-
data[(pos.x - 1) + (pos.y) * module_count] = 0
1174-
data[(pos.x + 1) + (pos.y) * module_count] = 0
1185+
data[(pos.x - 1 + idx) + (pos.y - 1) * module_count] = _LIGHT
1186+
data[(pos.x - 1 + idx) + (pos.y + 1) * module_count] = _LIGHT
1187+
data[(pos.x - 1) + (pos.y) * module_count] = _LIGHT
1188+
data[(pos.x + 1) + (pos.y) * module_count] = _LIGHT
11751189

11761190
static func _place_separators(data: PackedByteArray, module_count: int) -> void:
11771191
for idx: int in range(8):
11781192
# upper left
1179-
data[idx + 7 * module_count] = 0
1180-
data[7 + idx * module_count] = 0
1193+
data[idx + 7 * module_count] = _LIGHT
1194+
data[7 + idx * module_count] = _LIGHT
11811195
# lower left
1182-
data[idx + (module_count - 8) * module_count] = 0
1183-
data[(module_count - 8) + idx * module_count] = 0
1196+
data[idx + (module_count - 8) * module_count] = _LIGHT
1197+
data[(module_count - 8) + idx * module_count] = _LIGHT
11841198
# upper right
1185-
data[(module_count - idx - 1) + 7 * module_count] = 0
1186-
data[7 + (module_count - idx - 1) * module_count] = 0
1199+
data[(module_count - idx - 1) + 7 * module_count] = _LIGHT
1200+
data[7 + (module_count - idx - 1) * module_count] = _LIGHT
11871201

11881202
static func _place_timing_patterns(data: PackedByteArray, module_count: int) -> void:
11891203
for idx: int in range(module_count - 6 * 2):
11901204
data[6 + idx + 6 * module_count] = (idx + 1) % 2
11911205
data[6 + (6 + idx) * module_count] = (idx + 1) % 2
11921206

11931207
static func _is_data_module(module_count: int, alignment_pattern_pos: Array[Vector2i], pos: Vector2i) -> bool:
1194-
# finder with separation and format information area: upper left finder, upper right finder, lower left finder
1195-
# dark module is also included
1196-
if (pos.x <= 8 && pos.y <= 8) || (pos.x >= (module_count - 8) && pos.y <= 8) || (pos.x <= 8 && pos.y >= (module_count - 8)):
1197-
return false
1198-
# timing pattern
1199-
if pos.x == 6 || pos.y == 6:
1208+
# finder patterns with separators and format information area
1209+
if (pos.x <= 8 && pos.y <= 8) || \
1210+
(pos.x >= module_count - 8 && pos.y <= 8) || \
1211+
(pos.x <= 8 && pos.y >= module_count - 8):
12001212
return false
1201-
# version information area
1202-
# for version >= 7, upper and lower
1203-
# this check, will also success if it is in a finder area
1204-
if module_count >= 45 && ((pos.x >= module_count - 11 && pos.y <= 5) || (pos.x <= 5 && pos.y >= module_count - 11)):
1213+
1214+
# timing patterns (run through middle, already excluded in finder areas)
1215+
if (pos.x == 6 && pos.y >= 8 && pos.y < module_count - 8) || \
1216+
(pos.y == 6 && pos.x >= 8 && pos.x < module_count - 8):
12051217
return false
1206-
1207-
# check if in alignment pattern
1218+
1219+
# version information area (version >= 7 only)
1220+
if module_count >= 45:
1221+
# Bottom-left: 6 rows × 3 columns
1222+
if pos.x <= 5 && pos.y >= module_count - 11 && pos.y <= module_count - 9:
1223+
return false
1224+
# Top-right: 3 rows × 6 columns
1225+
if pos.y <= 5 && pos.x >= module_count - 11 && pos.x <= module_count - 9:
1226+
return false
1227+
1228+
# alignment patterns
12081229
for align_pos: Vector2i in alignment_pattern_pos:
1209-
if pos.x >= align_pos.x - 2 && pos.x <= align_pos.x + 2 && pos.y >= align_pos.y - 2 && pos.y <= align_pos.y + 2:
1230+
if pos.x >= align_pos.x - 2 && pos.x <= align_pos.x + 2 && \
1231+
pos.y >= align_pos.y - 2 && pos.y <= align_pos.y + 2:
12101232
return false
1211-
1233+
12121234
return true
12131235

12141236
static func _place_data(data: PackedByteArray, module_count: int, alignment_pattern_pos: Array[Vector2i], structured_data: BitStream) -> void:
@@ -1283,34 +1305,34 @@ static func _calc_mask_rating(data: PackedByteArray, module_count: int) -> int:
12831305
for y: int in range(module_count):
12841306
for x: int in range(module_count - 6):
12851307
var start_idx: int = x + y * module_count
1286-
if (!data[start_idx]
1287-
&& data[start_idx + 1]
1288-
&& !data[start_idx + 2]
1289-
&& !data[start_idx + 3]
1290-
&& !data[start_idx + 4]
1291-
&& data[start_idx + 5]
1292-
&& !data[start_idx + 6]):
1293-
if x >= 4 && data[start_idx - 1] && data[start_idx - 2] && data[start_idx - 3] && data[start_idx - 4]:
1308+
if (data[start_idx]
1309+
&& !data[start_idx + 1]
1310+
&& data[start_idx + 2]
1311+
&& data[start_idx + 3]
1312+
&& data[start_idx + 4]
1313+
&& !data[start_idx + 5]
1314+
&& data[start_idx + 6]):
1315+
if x >= 4 && !data[start_idx - 1] && !data[start_idx - 2] && !data[start_idx - 3] && !data[start_idx - 4]:
12941316
rating += 40
1295-
if x <= (module_count - 10) && data[start_idx + 7] && data[start_idx + 8] && data[start_idx + 9] && data[start_idx + 10]:
1317+
if x <= (module_count - 11) && !data[start_idx + 7] && !data[start_idx + 8] && !data[start_idx + 9] && !data[start_idx + 10]:
12961318
rating += 40
12971319

12981320
for x: int in range(module_count):
12991321
for y: int in range(module_count - 6):
1300-
if (!data[x + y * module_count]
1301-
&& data[x + (y + 1) * module_count]
1302-
&& !data[x + (y + 2) * module_count]
1303-
&& !data[x + (y + 3) * module_count]
1304-
&& !data[x + (y + 4) * module_count]
1305-
&& data[x + (y + 5) * module_count]
1306-
&& !data[x + (y + 6) * module_count]):
1307-
if y >= 4 && data[x + (y - 1) * module_count] && data[x + (y - 2) * module_count] && data[x + (y - 3) * module_count] && data[x + (y - 4) * module_count]:
1322+
if (data[x + y * module_count]
1323+
&& !data[x + (y + 1) * module_count]
1324+
&& data[x + (y + 2) * module_count]
1325+
&& data[x + (y + 3) * module_count]
1326+
&& data[x + (y + 4) * module_count]
1327+
&& !data[x + (y + 5) * module_count]
1328+
&& data[x + (y + 6) * module_count]):
1329+
if y >= 4 && !data[x + (y - 1) * module_count] && !data[x + (y - 2) * module_count] && !data[x + (y - 3) * module_count] && !data[x + (y - 4) * module_count]:
13081330
rating += 40
1309-
if y <= (module_count - 11) && data[x + (y + 7) * module_count] && data[x + (y + 8) * module_count] && data[x + (y + 9) * module_count] && data[x + (y + 10) * module_count]:
1331+
if y <= (module_count - 11) && !data[x + (y + 7) * module_count] && !data[x + (y + 8) * module_count] && !data[x + (y + 9) * module_count] && !data[x + (y + 10) * module_count]:
13101332
rating += 40
13111333

13121334
# condition 4
1313-
var dark_mods: int = data.count(0)
1335+
var dark_mods: int = data.count(_DARK)
13141336
var ratio: float = dark_mods / float(module_count * module_count)
13151337
var percent: int = int((ratio * 100) - 50)
13161338
rating += absi(percent) / 5 * 10
@@ -1382,7 +1404,7 @@ func _place_modules(structured_data: BitStream) -> PackedByteArray:
13821404
_place_timing_patterns(qr_data, module_count)
13831405

13841406
# dark module
1385-
qr_data[8 + (module_count - 8) * module_count] = 1
1407+
qr_data[8 + (module_count - 8) * module_count] = _DARK
13861408

13871409
# place data
13881410
_place_data(qr_data, module_count, alignment_pattern_pos, structured_data)

doc/docs/addons/qr_code.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ Shift JIS encoding utility.
158158

159159
## Changelog
160160

161+
### 1.3.1
162+
163+
- Fix various bugs, which could lead to crashes and too large versions being selected
164+
161165
### 1.3.0
162166

163167
- Upgrade `.import`s to Godot 4.6

examples/qr_code/main.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func _on_input_data_text_text_changed() -> void:
3333

3434
func _on_encoding_item_selected(_index: int) -> void:
3535
self._qr_rect.mode = self._encoding.get_selected_id() as QRCode.Mode
36-
if self._qr_rect.mode == QRCode.Mode.BYTE && !self._qr_rect.use_eci:
36+
if self._qr_rect.mode == QRCode.Mode.BYTE:
3737
self._use_eci.button_pressed = true
3838
self._use_eci.disabled = true
3939
else:

0 commit comments

Comments
 (0)