@@ -572,8 +572,9 @@ def line(x0, y0, x1, y1, **kwargs):
572
572
if stroke is not None and strokewidth > 0 :
573
573
glColor4f (stroke [0 ], stroke [1 ], stroke [2 ], stroke [3 ] * _alpha )
574
574
glLineWidth (strokewidth )
575
- glLineDash (strokestyle )
576
- glBegin (GL_LINE_LOOP )
575
+ if strokestyle != _strokestyle :
576
+ glLineDash (strokestyle )
577
+ glBegin (GL_LINES )
577
578
glVertex2f (x0 , y0 )
578
579
glVertex2f (x1 , y1 )
579
580
glEnd ()
@@ -598,7 +599,7 @@ def rect(x, y, width, height, **kwargs):
598
599
glVertex2f (x + width , y + height )
599
600
glVertex2f (x , y + height )
600
601
glEnd ()
601
-
602
+
602
603
def triangle (x1 , y1 , x2 , y2 , x3 , y3 , ** kwargs ):
603
604
""" Draws the triangle created by connecting the three given points.
604
605
The current stroke, strokewidth and fill color are applied.
@@ -608,10 +609,11 @@ def triangle(x1, y1, x2, y2, x3, y3, **kwargs):
608
609
if clr is not None and (i == 0 or strokewidth > 0 ):
609
610
if i == 1 :
610
611
glLineWidth (strokewidth )
611
- glLineDash (strokestyle )
612
+ if strokestyle != _strokestyle :
613
+ glLineDash (strokestyle )
612
614
glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
613
615
# Note: this performs equally well as when using precompile().
614
- glBegin ((GL_POLYGON , GL_LINE_LOOP )[i ])
616
+ glBegin ((GL_TRIANGLES , GL_LINE_LOOP )[i ])
615
617
glVertex2f (x1 , y1 )
616
618
glVertex2f (x2 , y2 )
617
619
glVertex2f (x3 , y3 )
@@ -626,19 +628,25 @@ def ellipse(x, y, width, height, segments=ELLIPSE_SEGMENTS, **kwargs):
626
628
if not segments in _ellipses :
627
629
# For the given amount of line segments, calculate the ellipse once.
628
630
# Then reuse the cached ellipse by scaling it to the desired size.
629
- _ellipses [segments ] = []
630
- for mode in (GL_POLYGON , GL_LINE_LOOP ):
631
- _ellipses [segments ].append (precompile (lambda :(
632
- glBegin (mode ),
633
- [glVertex2f (cos (t )/ 2 , sin (t )/ 2 ) for t in [2 * pi * i / segments for i in range (segments )]],
634
- glEnd ()
635
- )))
631
+ commands = []
632
+ f = 2 * pi / segments
633
+ v = [(cos (t )/ 2 , sin (t )/ 2 ) for t in [i * f for i in range (segments )+ [0 ]]]
634
+ for mode in (GL_TRIANGLE_FAN , GL_LINE_LOOP ):
635
+ commands .append (precompile (lambda :(
636
+ glBegin (mode ),
637
+ [glVertex2f (x , y ) for (x , y ) in v ],
638
+ glEnd ()
639
+ )))
640
+
641
+ _ellipses [segments ] = commands
642
+
636
643
fill , stroke , strokewidth , strokestyle = color_mixin (** kwargs )
637
644
for i , clr in enumerate ((fill , stroke )):
638
645
if clr is not None and (i == 0 or strokewidth > 0 ):
639
646
if i == 1 :
640
647
glLineWidth (strokewidth )
641
- glLineDash (strokestyle )
648
+ if strokestyle != _strokestyle :
649
+ glLineDash (strokestyle )
642
650
glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
643
651
glPushMatrix ()
644
652
glTranslatef (x , y , 0 )
@@ -673,20 +681,63 @@ def arrow(x, y, width, **kwargs):
673
681
glVertex2f (x , y )
674
682
glEnd ()
675
683
684
+ def gcd (a , b ):
685
+ return gcd (b , a % b ) if b else a
686
+
687
+ _stars = {} #TODO: LRU?
688
+ def fast_star (x , y , points = 20 , outer = 100 , inner = 50 , ** kwargs ):
689
+ """ Draws a star with the given points, outer radius and inner radius.
690
+ The current stroke, strokewidth and fill color are applied.
691
+ """
692
+ scale = gcd (inner , outer )
693
+ iscale = inner / scale
694
+ oscale = outer / scale
695
+ cached = _stars .get ((points , iscale , oscale ), [])
696
+ if not cached :
697
+ radii = [oscale , iscale ] * int (points + 1 ); radii .pop () # which radius?
698
+ f = pi / points
699
+ v = [(r * sin (i * f ), r * cos (i * f )) for i , r in enumerate (radii )]
700
+ cached .append (precompile (lambda :(
701
+ glBegin (GL_TRIANGLE_FAN ),
702
+ glVertex2f (0 , 0 ),
703
+ [glVertex2f (vx , vy ) for (vx , vy ) in v ],
704
+ glEnd ()
705
+ )))
706
+ cached .append (precompile (lambda :(
707
+ glBegin (GL_LINE_LOOP ),
708
+ [glVertex2f (vx , vy ) for (vx , vy ) in v ],
709
+ glEnd ()
710
+ )))
711
+ _stars [(points , iscale , oscale )] = cached
712
+
713
+ fill , stroke , strokewidth , strokestyle = color_mixin (** kwargs )
714
+ for i , clr in enumerate ((fill , stroke )):
715
+ if clr is not None and (i == 0 or strokewidth > 0 ):
716
+ if i == 1 :
717
+ glLineWidth (strokewidth )
718
+ if strokestyle != _strokestyle :
719
+ glLineDash (strokestyle )
720
+ glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
721
+ glPushMatrix ()
722
+ glTranslatef (x , y , 0 )
723
+ glScalef (scale , scale , 1 )
724
+ glCallList (cached [i ])
725
+ glPopMatrix ()
726
+
676
727
def star (x , y , points = 20 , outer = 100 , inner = 50 , ** kwargs ):
677
728
""" Draws a star with the given points, outer radius and inner radius.
678
729
The current stroke, strokewidth and fill color are applied.
730
+ This is about 20x slower than fast_star; use it only if you need the path returned.
679
731
"""
680
- # GL_POLYGON only works with convex polygons,
681
- # so we use a BezierPath (which does tessellation for fill colors).
682
732
p = BezierPath (** kwargs )
683
733
p .moveto (x , y + outer )
684
734
for i in range (0 , int (2 * points )+ 1 ):
685
735
r = (outer , inner )[i % 2 ]
686
736
a = pi * i / points
687
737
p .lineto (x + r * sin (a ), y + r * cos (a ))
688
738
p .closepath ()
689
- if kwargs .get ("draw" , True ):
739
+
740
+ if kwargs .get ("draw" , True ):
690
741
p .draw (** kwargs )
691
742
return p
692
743
@@ -1454,7 +1505,8 @@ def texture(img, data=None):
1454
1505
return _texture_cache [img ]
1455
1506
# Image file path, load it, cache it, return texture.
1456
1507
if isinstance (img , basestring ):
1457
- try : cache (img , pyglet .image .load (img ).get_texture ())
1508
+ try :
1509
+ cache (img , pyglet .image .load (img ).get_texture ())
1458
1510
except IOError :
1459
1511
raise ImageError , "can't load image from %s" % repr (img )
1460
1512
return _texture_cache [img ]
0 commit comments