@@ -681,44 +681,59 @@ def arrow(x, y, width, **kwargs):
681681 glVertex2f (x , y )
682682 glEnd ()
683683
684+ def gcd (a , b ):
685+ return gcd (b , a % b ) if b else a
686+
687+ _stars = {} #TODO: LRU?
684688def star (x , y , points = 20 , outer = 100 , inner = 50 , ** kwargs ):
685689 """ Draws a star with the given points, outer radius and inner radius.
686690 The current stroke, strokewidth and fill color are applied.
687691 """
688- radii = [outer , inner ] * int (points + 1 ); radii .pop () # which radius?
689- f = pi / points
690- v = [(x + r * sin (i * f ), y + r * cos (i * f )) for i , r in enumerate (radii )]
691-
692692 if kwargs .get ("draw" , True ):
693- fill , stroke , strokewidth , strokestyle = color_mixin (** kwargs )
694-
695- if fill is not None :
696- glColor4f (fill [0 ], fill [1 ], fill [2 ], fill [3 ] * _alpha )
697-
698- glBegin (GL_TRIANGLE_FAN )
699- glVertex2f (x , y )
700- for (vx , vy ) in v :
701- glVertex2f (vx , vy )
702- glEnd ()
703-
704- if stroke is not None and 0 < strokewidth :
705- glLineWidth (strokewidth )
706- if strokestyle != _strokestyle :
707- glLineDash (strokestyle )
708- glColor4f (stroke [0 ], stroke [1 ], stroke [2 ], stroke [3 ] * _alpha )
693+ scale = gcd (inner , outer )
694+ iscale = inner / scale
695+ oscale = outer / scale
696+ cached = _stars .get ((points , iscale , oscale ), [])
697+ if not cached :
698+ radii = [oscale , iscale ] * int (points + 1 ); radii .pop () # which radius?
699+ f = pi / points
700+ v = [(r * sin (i * f ), r * cos (i * f )) for i , r in enumerate (radii )]
701+ cached .append (precompile (lambda :(
702+ glBegin (GL_TRIANGLE_FAN ),
703+ glVertex2f (0 , 0 ),
704+ [glVertex2f (vx , vy ) for (vx , vy ) in v ],
705+ glEnd ()
706+ )))
707+ cached .append (precompile (lambda :(
708+ glBegin (GL_LINE_LOOP ),
709+ [glVertex2f (vx , vy ) for (vx , vy ) in v ],
710+ glEnd ()
711+ )))
712+ _stars [(points , iscale , oscale )] = cached
709713
710- glBegin (GL_LINE_LOOP )
711- for (vx , vy ) in v :
712- glVertex2f (vx , vy )
713- glEnd ()
714+ fill , stroke , strokewidth , strokestyle = color_mixin (** kwargs )
715+ for i , clr in enumerate ((fill , stroke )):
716+ if clr is not None and (i == 0 or strokewidth > 0 ):
717+ if i == 1 :
718+ glLineWidth (strokewidth )
719+ if strokestyle != _strokestyle :
720+ glLineDash (strokestyle )
721+ glColor4f (clr [0 ], clr [1 ], clr [2 ], clr [3 ] * _alpha )
722+ glPushMatrix ()
723+ glTranslatef (x , y , 0 )
724+ glScalef (scale , scale , 1 )
725+ glCallList (cached [i ])
726+ glPopMatrix ()
714727 else :
715728 # For whatever reason, the original api specified that you
716- # can get the path to the star. This is about 20x slower,
729+ # can get the path to the star. This is about 30x slower,
717730 # but I'm keeping it here for backwards compatibility.
718731 p = BezierPath (** kwargs )
719732 p .moveto (x , y + outer )
720- for (vx , vy ) in v :
721- p .lineto (vx , vy )
733+ for i in range (0 , int (2 * points )+ 1 ):
734+ r = (outer , inner )[i % 2 ]
735+ a = pi * i / points
736+ p .lineto (x + r * sin (a ), y + r * cos (a ))
722737 p .closepath ()
723738 return p
724739
@@ -1486,7 +1501,8 @@ def texture(img, data=None):
14861501 return _texture_cache [img ]
14871502 # Image file path, load it, cache it, return texture.
14881503 if isinstance (img , basestring ):
1489- try : cache (img , pyglet .image .load (img ).get_texture ())
1504+ try :
1505+ cache (img , pyglet .image .load (img ).get_texture ())
14901506 except IOError :
14911507 raise ImageError , "can't load image from %s" % repr (img )
14921508 return _texture_cache [img ]
0 commit comments