@@ -572,8 +572,9 @@ def line(x0, y0, x1, y1, **kwargs):
572572 if stroke is not None and strokewidth > 0 :
573573 glColor4f (stroke [0 ], stroke [1 ], stroke [2 ], stroke [3 ] * _alpha )
574574 glLineWidth (strokewidth )
575- glLineDash (strokestyle )
576- glBegin (GL_LINE_LOOP )
575+ if strokestyle != _strokestyle :
576+ glLineDash (strokestyle )
577+ glBegin (GL_LINES )
577578 glVertex2f (x0 , y0 )
578579 glVertex2f (x1 , y1 )
579580 glEnd ()
@@ -598,7 +599,7 @@ def rect(x, y, width, height, **kwargs):
598599 glVertex2f (x + width , y + height )
599600 glVertex2f (x , y + height )
600601 glEnd ()
601-
602+
602603def triangle (x1 , y1 , x2 , y2 , x3 , y3 , ** kwargs ):
603604 """ Draws the triangle created by connecting the three given points.
604605 The current stroke, strokewidth and fill color are applied.
@@ -608,10 +609,11 @@ def triangle(x1, y1, x2, y2, x3, y3, **kwargs):
608609 if clr is not None and (i == 0 or strokewidth > 0 ):
609610 if i == 1 :
610611 glLineWidth (strokewidth )
611- glLineDash (strokestyle )
612+ if strokestyle != _strokestyle :
613+ glLineDash (strokestyle )
612614 glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
613615 # 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 ])
615617 glVertex2f (x1 , y1 )
616618 glVertex2f (x2 , y2 )
617619 glVertex2f (x3 , y3 )
@@ -626,19 +628,25 @@ def ellipse(x, y, width, height, segments=ELLIPSE_SEGMENTS, **kwargs):
626628 if not segments in _ellipses :
627629 # For the given amount of line segments, calculate the ellipse once.
628630 # 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+
636643 fill , stroke , strokewidth , strokestyle = color_mixin (** kwargs )
637644 for i , clr in enumerate ((fill , stroke )):
638645 if clr is not None and (i == 0 or strokewidth > 0 ):
639646 if i == 1 :
640647 glLineWidth (strokewidth )
641- glLineDash (strokestyle )
648+ if strokestyle != _strokestyle :
649+ glLineDash (strokestyle )
642650 glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
643651 glPushMatrix ()
644652 glTranslatef (x , y , 0 )
@@ -673,20 +681,63 @@ def arrow(x, y, width, **kwargs):
673681 glVertex2f (x , y )
674682 glEnd ()
675683
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+
676727def star (x , y , points = 20 , outer = 100 , inner = 50 , ** kwargs ):
677728 """ Draws a star with the given points, outer radius and inner radius.
678729 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.
679731 """
680- # GL_POLYGON only works with convex polygons,
681- # so we use a BezierPath (which does tessellation for fill colors).
682732 p = BezierPath (** kwargs )
683733 p .moveto (x , y + outer )
684734 for i in range (0 , int (2 * points )+ 1 ):
685735 r = (outer , inner )[i % 2 ]
686736 a = pi * i / points
687737 p .lineto (x + r * sin (a ), y + r * cos (a ))
688738 p .closepath ()
689- if kwargs .get ("draw" , True ):
739+
740+ if kwargs .get ("draw" , True ):
690741 p .draw (** kwargs )
691742 return p
692743
@@ -1454,7 +1505,8 @@ def texture(img, data=None):
14541505 return _texture_cache [img ]
14551506 # Image file path, load it, cache it, return texture.
14561507 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 ())
14581510 except IOError :
14591511 raise ImageError , "can't load image from %s" % repr (img )
14601512 return _texture_cache [img ]
0 commit comments