@@ -681,6 +681,9 @@ const _ALIGNMENT_PATTERN_POSITIONS: Array[Array] = [
681681## remainder bits after structured data bits
682682const _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+
684687static var _number_rx : RegEx = RegEx .create_from_string ("[^\\ d]*" )
685688static 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:
754757func 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:
783788func 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
811824static func _get_state (value : int , idx : int ) -> bool :
812- return ( value & (1 << idx ))
825+ return value & (1 << idx ) != 0
813826
814827func _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
11531167static 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
11661180static 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
11761190static 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
11881202static 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
11931207static 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
12141236static 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 )
0 commit comments