@@ -222,72 +222,15 @@ def circle(
222222 ellipse_xy = (xy [0 ] - radius , xy [1 ] - radius , xy [0 ] + radius , xy [1 ] + radius )
223223 self .ellipse (ellipse_xy , fill , outline , width )
224224
225- def _normalize_points (self , xy : Coords ) -> list [Sequence [float ]]:
226- """Convert various coordinate formats to a list of (x, y) tuples ."""
225+ def _normalize_coords (self , xy : Coords ) -> Sequence [Sequence [float ]]:
226+ """Normalize 1 or 2 dimensional coord sequence into 2d sequence ."""
227227 if isinstance (xy [0 ], (list , tuple )):
228- return list ( cast ("Sequence[Sequence[float]]" , xy ) )
228+ return cast ("Sequence[Sequence[float]]" , xy )
229229 else :
230- flat_xy = cast ("Sequence[float]" , xy )
231- return [flat_xy [i : i + 2 ] for i in range (0 , len (flat_xy ), 2 )]
232-
233- def _draw_dashed_line (
234- self ,
235- p1 : Sequence [float ],
236- p2 : Sequence [float ],
237- dash : tuple [int , ...],
238- ink : int ,
239- width : int ,
240- dash_offset : int ,
241- ) -> int :
242- """Draw a single dashed line segment between two points.
243-
244- Returns the updated dash_offset for continuing the pattern
245- along the next segment.
246- """
247- dx = p2 [0 ] - p1 [0 ]
248- dy = p2 [1 ] - p1 [1 ]
249- segment_length = math .hypot (dx , dy )
250- if segment_length == 0 :
251- return dash_offset
252-
253- vx = dx / segment_length
254- vy = dy / segment_length
255-
256- remaining = segment_length
257- x , y = p1
258-
259- # Determine where we are in the dash pattern
260- dash_cycle_length = sum (dash )
261- offset = dash_offset % dash_cycle_length
262- dash_index = 0
263- consumed = 0
264- for i , d in enumerate (dash ):
265- if consumed + d > offset :
266- dash_index = i
267- break
268- consumed += d
269- pixels_used : float = offset - consumed
270-
271- while remaining > 0.5 :
272- current_dash_length = dash [dash_index % len (dash )]
273- step = min (current_dash_length - pixels_used , remaining )
274-
275- nx = x + vx * step
276- ny = y + vy * step
277-
278- if dash_index % 2 == 0 :
279- self .draw .draw_lines ([(x , y ), (nx , ny )], ink , width )
280-
281- x = nx
282- y = ny
283- remaining -= step
284- pixels_used += step
285-
286- if pixels_used >= current_dash_length :
287- pixels_used = 0
288- dash_index += 1
289-
290- return (dash_offset + int (round (segment_length ))) % dash_cycle_length
230+ return [
231+ cast ("Sequence[float]" , tuple (xy [i : i + 2 ]))
232+ for i in range (0 , len (xy ), 2 )
233+ ]
291234
292235 def line (
293236 self ,
@@ -303,27 +246,22 @@ def line(
303246 return
304247
305248 if dash is not None :
306- if len (dash ) == 0 :
249+ if len (dash ) == 0 or any ( not isinstance ( v , int ) for v in dash ) :
307250 msg = "dash must be a non-empty tuple of ints"
308251 raise ValueError (msg )
309- points = self ._normalize_points (xy )
310- dash_offset = 0
311- for i in range (len (points ) - 1 ):
312- dash_offset = self ._draw_dashed_line (
313- points [i ], points [i + 1 ], dash , ink , width , dash_offset
314- )
252+ self .draw .draw_lines (xy , ink , 1 , dash )
315253 else :
316254 self .draw .draw_lines (xy , ink , width )
317255 if joint == "curve" and width > 4 :
318- joint_points = self ._normalize_points (xy )
319- for i in range (1 , len (joint_points ) - 1 ):
320- point = joint_points [i ]
256+ points = self ._normalize_coords (xy )
257+ for i in range (1 , len (points ) - 1 ):
258+ point = points [i ]
321259 angles = [
322260 math .degrees (math .atan2 (end [0 ] - start [0 ], start [1 ] - end [1 ]))
323261 % 360
324262 for start , end in (
325- (joint_points [i - 1 ], point ),
326- (point , joint_points [i + 1 ]),
263+ (points [i - 1 ], point ),
264+ (point , points [i + 1 ]),
327265 )
328266 ]
329267 if angles [0 ] == angles [1 ]:
@@ -425,18 +363,10 @@ def polygon(
425363 return
426364
427365 if dash is not None :
428- if len (dash ) == 0 :
366+ if len (dash ) == 0 or any ( not isinstance ( v , int ) for v in dash ) :
429367 msg = "dash must be a non-empty tuple of ints"
430368 raise ValueError (msg )
431- points = self ._normalize_points (xy )
432- # Close the polygon by connecting last point to first
433- if points [0 ] != points [- 1 ]:
434- points .append (points [0 ])
435- dash_offset = 0
436- for i in range (len (points ) - 1 ):
437- dash_offset = self ._draw_dashed_line (
438- points [i ], points [i + 1 ], dash , ink , width , dash_offset
439- )
369+ self .draw .draw_polygon (xy , ink , 0 , 1 , dash )
440370 elif width == 1 :
441371 self .draw .draw_polygon (xy , ink , 0 , width )
442372 elif self .im is not None :
@@ -447,7 +377,7 @@ def polygon(
447377 draw = Draw (mask )
448378 draw .draw .draw_polygon (xy , mask_ink , 1 )
449379
450- self .draw .draw_polygon (xy , ink , 0 , width * 2 - 1 , mask .im )
380+ self .draw .draw_polygon (xy , ink , 0 , width * 2 - 1 , None , mask .im )
451381
452382 def regular_polygon (
453383 self ,
@@ -478,27 +408,21 @@ def rectangle(
478408 return
479409
480410 if dash is not None :
481- if len (dash ) == 0 :
411+ if len (dash ) == 0 or any ( not isinstance ( v , int ) for v in dash ) :
482412 msg = "dash must be a non-empty tuple of ints"
483413 raise ValueError (msg )
484- (x0 , y0 ), (x1 , y1 ) = self ._normalize_points (xy )
485- rect_points = [
486- (x0 , y0 ),
487- (x1 , y0 ),
488- (x1 , y1 ),
489- (x0 , y1 ),
490- (x0 , y0 ),
491- ]
492- dash_offset = 0
493- for i in range (4 ):
494- dash_offset = self ._draw_dashed_line (
495- rect_points [i ],
496- rect_points [i + 1 ],
497- dash ,
498- ink ,
499- width ,
500- dash_offset ,
501- )
414+ self .draw .draw_lines (
415+ [
416+ (xy [0 ], xy [1 ]),
417+ (xy [2 ], xy [1 ]),
418+ (xy [2 ], xy [3 ]),
419+ (xy [0 ], xy [3 ]),
420+ (xy [0 ], xy [1 ]),
421+ ],
422+ ink ,
423+ 1 ,
424+ dash ,
425+ )
502426 else :
503427 self .draw .draw_rectangle (xy , ink , 0 , width )
504428
@@ -513,7 +437,7 @@ def rounded_rectangle(
513437 corners : tuple [bool , bool , bool , bool ] | None = None ,
514438 ) -> None :
515439 """Draw a rounded rectangle."""
516- (x0 , y0 ), (x1 , y1 ) = self ._normalize_points (xy )
440+ (x0 , y0 ), (x1 , y1 ) = self ._normalize_coords (xy )
517441 if x1 < x0 :
518442 msg = "x1 must be greater than or equal to x0"
519443 raise ValueError (msg )
0 commit comments