@@ -204,26 +204,92 @@ fn qr_code(
204204
205205 let size = qr_code. size ( ) ;
206206 let mut vector = Vector :: default ( ) ;
207- let offset = DVec2 :: splat ( size as f64 / -2. ) ;
208-
209- for y in 0 ..size {
210- let mut x = 0 ;
211- while x < size {
212- if qr_code. get_module ( x, y) {
213- let start_x = x;
214- x += 1 ;
215- if merge {
216- while x < size && qr_code. get_module ( x, y) {
217- x += 1 ;
207+ let offset = DVec2 :: splat ( 0.0 ) ;
208+
209+ if merge {
210+ use std:: collections:: { HashMap , HashSet , VecDeque } ;
211+
212+ let mut remaining: HashSet < ( i32 , i32 ) > = HashSet :: new ( ) ;
213+ for y in 0 ..size {
214+ for x in 0 ..size {
215+ if qr_code. get_module ( x, y) {
216+ remaining. insert ( ( x, y) ) ;
217+ }
218+ }
219+ }
220+
221+ while let Some ( & ( start_x, start_y) ) = remaining. iter ( ) . next ( ) {
222+ let mut island = HashSet :: new ( ) ;
223+ let mut queue = VecDeque :: new ( ) ;
224+ queue. push_back ( ( start_x, start_y) ) ;
225+ remaining. remove ( & ( start_x, start_y) ) ;
226+
227+ while let Some ( ( x, y) ) = queue. pop_front ( ) {
228+ island. insert ( ( x, y) ) ;
229+ for ( dx, dy) in [ ( 0 , 1 ) , ( 0 , -1 ) , ( 1 , 0 ) , ( -1 , 0 ) ] {
230+ let nx = x + dx;
231+ let ny = y + dy;
232+ if remaining. remove ( & ( nx, ny) ) {
233+ queue. push_back ( ( nx, ny) ) ;
234+ }
235+ }
236+ }
237+
238+ let mut island_edges = HashSet :: new ( ) ;
239+ for & ( x, y) in & island {
240+ for ( p1, p2) in [ ( ( x, y) , ( x + 1 , y) ) , ( ( x + 1 , y) , ( x + 1 , y + 1 ) ) , ( ( x + 1 , y + 1 ) , ( x, y + 1 ) ) , ( ( x, y + 1 ) , ( x, y) ) ] {
241+ if !island_edges. remove ( & ( p2, p1) ) {
242+ island_edges. insert ( ( p1, p2) ) ;
243+ }
244+ }
245+ }
246+
247+ let mut adjacency: HashMap < ( i32 , i32 ) , Vec < ( i32 , i32 ) > > = HashMap :: new ( ) ;
248+ for ( p1, p2) in island_edges {
249+ adjacency. entry ( p1) . or_default ( ) . push ( p2) ;
250+ }
251+
252+ while let Some ( & start_point) = adjacency. keys ( ) . next ( ) {
253+ let mut loop_points = Vec :: new ( ) ;
254+ let mut current = start_point;
255+
256+ loop {
257+ loop_points. push ( DVec2 :: new ( current. 0 as f64 , current. 1 as f64 ) ) ;
258+ let next = adjacency. get_mut ( & current) . and_then ( |n| n. pop ( ) ) . unwrap ( ) ;
259+ if adjacency. get ( & current) . map_or ( false , |n| n. is_empty ( ) ) {
260+ adjacency. remove ( & current) ;
261+ }
262+ current = next;
263+ if current == start_point {
264+ break ;
218265 }
219266 }
220- let end_x = x;
221267
222- let corner1 = offset + DVec2 :: new ( start_x as f64 , y as f64 ) ;
223- let corner2 = offset + DVec2 :: new ( end_x as f64 , ( y + 1 ) as f64 ) ;
224- vector. append_subpath ( subpath:: Subpath :: new_rect ( corner1, corner2) , false ) ;
225- } else {
226- x += 1 ;
268+ if loop_points. len ( ) > 2 {
269+ let mut simplified = Vec :: new ( ) ;
270+ for i in 0 ..loop_points. len ( ) {
271+ let prev = loop_points[ ( i + loop_points. len ( ) - 1 ) % loop_points. len ( ) ] ;
272+ let curr = loop_points[ i] ;
273+ let next = loop_points[ ( i + 1 ) % loop_points. len ( ) ] ;
274+
275+ if ( curr - prev) . perp_dot ( next - curr) . abs ( ) > 1e-6 {
276+ simplified. push ( curr + offset) ;
277+ }
278+ }
279+ if !simplified. is_empty ( ) {
280+ vector. append_subpath ( subpath:: Subpath :: from_anchors ( simplified, true ) , false ) ;
281+ }
282+ }
283+ }
284+ }
285+ } else {
286+ for y in 0 ..size {
287+ for x in 0 ..size {
288+ if qr_code. get_module ( x, y) {
289+ let corner1 = offset + DVec2 :: new ( x as f64 , y as f64 ) ;
290+ let corner2 = corner1 + DVec2 :: splat ( 1. ) ;
291+ vector. append_subpath ( subpath:: Subpath :: new_rect ( corner1, corner2) , false ) ;
292+ }
227293 }
228294 }
229295 }
0 commit comments