annotate visualclient/gradients.py @ 54:c0b34039917a tip

Server: added an exposed function to log the start time of a performance (for log-to-audio sync)
author Mathieu Barthet <mathieu.barthet@eecs.qmul.ac.uk>
date Wed, 14 Oct 2015 19:20:08 +0100
parents 1adf97ba90c8
children
rev   line source
gyorgyf@5 1 #Copyright 2006 DR0ID <dr0id@bluewin.ch> http://mypage.bluewin.ch/DR0ID
gyorgyf@5 2 #
gyorgyf@5 3 #
gyorgyf@5 4 #
gyorgyf@5 5 """
gyorgyf@5 6 Allow to draw some gradients relatively easy.
gyorgyf@5 7 """
gyorgyf@5 8
gyorgyf@5 9 __author__ = "$Author: DR0ID $"
gyorgyf@5 10 __version__= "$Revision: 109 $"
gyorgyf@5 11 __date__ = "$Date: 2007-08-09 20:33:32 +0200 (Do, 09 Aug 2007) $"
gyorgyf@5 12
gyorgyf@5 13 import pygame
gyorgyf@5 14 import math
gyorgyf@5 15
gyorgyf@5 16 BLEND_MODES_AVAILABLE = False
gyorgyf@5 17 vernum = pygame.vernum
gyorgyf@5 18 if vernum[0]>=1 and vernum[1]>=8:
gyorgyf@5 19 BLEND_MODES_AVAILABLE = True
gyorgyf@5 20
gyorgyf@5 21
gyorgyf@5 22 class ColorInterpolator(object):
gyorgyf@5 23 '''
gyorgyf@5 24 ColorInterpolator(distance, color1, color2, rfunc, gfunc, bfunc, afunc)
gyorgyf@5 25
gyorgyf@5 26 interpolates a color over the distance using different functions for r,g,b,a
gyorgyf@5 27 separately (a= alpha).
gyorgyf@5 28 '''
gyorgyf@5 29 def __init__(self, distance, color1, color2, rfunc, gfunc, bfunc, afunc):
gyorgyf@5 30 object.__init__(self)
gyorgyf@5 31
gyorgyf@5 32 self.rInterpolator = FunctionInterpolator(color1[0], color2[0], distance, rfunc)
gyorgyf@5 33 self.gInterpolator = FunctionInterpolator(color1[1], color2[1], distance, gfunc)
gyorgyf@5 34 self.bInterpolator = FunctionInterpolator(color1[2], color2[2], distance, bfunc)
gyorgyf@5 35 if len(color1)==4 and len(color2)==4:
gyorgyf@5 36 self.aInterpolator = FunctionInterpolator(color1[3], color2[3], distance, afunc)
gyorgyf@5 37 else:
gyorgyf@5 38 self.aInterpolator = FunctionInterpolator(255, 255, distance, afunc)
gyorgyf@5 39
gyorgyf@5 40 def eval(self, x):
gyorgyf@5 41 '''
gyorgyf@5 42 eval(x) -> color
gyorgyf@5 43
gyorgyf@5 44 returns the color at the position 0<=x<=d (actually not bound to this interval).
gyorgyf@5 45 '''
gyorgyf@5 46 ## print "colorInterp x", x, self.rInterpolator.eval(x), self.gInterpolator.eval(x), self.bInterpolator.eval(x)
gyorgyf@5 47 return [self.rInterpolator.eval(x),
gyorgyf@5 48 self.gInterpolator.eval(x),
gyorgyf@5 49 self.bInterpolator.eval(x),
gyorgyf@5 50 self.aInterpolator.eval(x)]
gyorgyf@5 51
gyorgyf@5 52
gyorgyf@5 53
gyorgyf@5 54 class FunctionInterpolator(object):
gyorgyf@5 55 '''
gyorgyf@5 56 FunctionINterpolator(startvalue, endvalue, trange, func)
gyorgyf@5 57
gyorgyf@5 58 interpolates a function y=f(x) in the range trange with
gyorgyf@5 59 startvalue = f(0)
gyorgyf@5 60 endvalue = f(trange)
gyorgyf@5 61 using the function func
gyorgyf@5 62 '''
gyorgyf@5 63 def __init__(self, startvalue, endvalue, trange, func):
gyorgyf@5 64 object.__init__(self)
gyorgyf@5 65 # function
gyorgyf@5 66 self.func = func
gyorgyf@5 67 # y-scaling
gyorgyf@5 68 self.a = endvalue-startvalue
gyorgyf@5 69 if self.a == 0:
gyorgyf@5 70 self.a = 1.
gyorgyf@5 71 # x-scaling
gyorgyf@5 72 if trange!=0:
gyorgyf@5 73 self.b = 1./abs(trange)
gyorgyf@5 74 else:
gyorgyf@5 75 self.b = 1.
gyorgyf@5 76 # x-displacement
gyorgyf@5 77 self.c = 0
gyorgyf@5 78 # y-displacement
gyorgyf@5 79 self.d = min(max(startvalue,0),255)
gyorgyf@5 80
gyorgyf@5 81 def eval(self, x):
gyorgyf@5 82 '''
gyorgyf@5 83 eval(x)->float
gyorgyf@5 84
gyorgyf@5 85 return value at position x
gyorgyf@5 86 '''
gyorgyf@5 87 # make sure that the returned value is in [0,255]
gyorgyf@5 88 ## return int(round(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255)))
gyorgyf@5 89 return int(min(max(self.a*self.func(self.b*(x+self.c))+self.d, 0), 255))
gyorgyf@5 90
gyorgyf@5 91
gyorgyf@5 92
gyorgyf@5 93 ##def gradient(surface,
gyorgyf@5 94 ## startpoint,
gyorgyf@5 95 ## endpoint,
gyorgyf@5 96 ## startcolor,
gyorgyf@5 97 ## endcolor,
gyorgyf@5 98 ## Rfunc = (lambda x:x),
gyorgyf@5 99 ## Gfunc = (lambda x:x),
gyorgyf@5 100 ## Bfunc = (lambda x:x),
gyorgyf@5 101 ## Afunc = (lambda x:1),
gyorgyf@5 102 ## type = "line",
gyorgyf@5 103 ## mode = None ):
gyorgyf@5 104 ## '''
gyorgyf@5 105 ## surface : surface to draw on
gyorgyf@5 106 ## startpoint: (x,y) point on surface
gyorgyf@5 107 ## endpoint : (x,y) point on surface
gyorgyf@5 108 ## startcolor: (r,g,b,a) color at startpoint
gyorgyf@5 109 ## endcolor : (r,g,b,a) color at endpoint
gyorgyf@5 110 ## Rfunc : function y = f(x) with startcolor =f(0) and endcolor = f(1) where 0 is at startpoint and 1 at endpoint
gyorgyf@5 111 ## Gfunc : --- " ---
gyorgyf@5 112 ## Bfunc : --- " ---
gyorgyf@5 113 ## Afunc : --- " ---
gyorgyf@5 114 ## these functions are evaluated in the range 0 <= x <= 1 and 0<= y=f(x) <= 1
gyorgyf@5 115 ## type : "line", "circle" or "rect"
gyorgyf@5 116 ## mode : "+", "-", "*", None (how the pixels are drawen)
gyorgyf@5 117 ##
gyorgyf@5 118 ## returns : surface with the color characteristics w,h = (d, 256) and d = length of endpoint-startpoint
gyorgyf@5 119 ##
gyorgyf@5 120 ## '''
gyorgyf@5 121 ## dx = endpoint[0]-startpoint[0]
gyorgyf@5 122 ## dy = endpoint[1]-startpoint[1]
gyorgyf@5 123 ## d = int(round(math.hypot(dx, dy)))
gyorgyf@5 124 ## angle = math.degrees( math.atan2(dy, dx) )
gyorgyf@5 125 ##
gyorgyf@5 126 ## color = ColorInterpolator(d, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 127 ##
gyorgyf@5 128 ## if type=="line":
gyorgyf@5 129 ## h = int(2.*math.hypot(*surface.get_size()))
gyorgyf@5 130 ### bigSurf = pygame.Surface((d, h)).convert_alpha()
gyorgyf@5 131 ## bigSurf = pygame.Surface((d, h), pygame.SRCALPHA)#.convert_alpha()
gyorgyf@5 132 ### bigSurf = pygame.Surface((d, 1), pygame.SRCALPHA)#.convert_alpha()
gyorgyf@5 133 ## bigSurf.lock()
gyorgyf@5 134 ## bigSurf.fill((0,0,0,0))
gyorgyf@5 135 ## bigSurf.set_colorkey((0,0,0,0))
gyorgyf@5 136 ## for x in range(d):
gyorgyf@5 137 ## pygame.draw.line(bigSurf, color.eval(x), (x,0), (x,h), 1)
gyorgyf@5 138 ### for x in range(d):
gyorgyf@5 139 ### bigSurf.set_at((x, 0), color.eval(x))
gyorgyf@5 140 ### bigSurf = pygame.transform.scale(bigSurf, (d, h))
gyorgyf@5 141 ##
gyorgyf@5 142 ## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1)
gyorgyf@5 143 ## bigSurf.set_colorkey((0,0,0, 0))
gyorgyf@5 144 ## rect = bigSurf.get_rect()
gyorgyf@5 145 ## srect = pygame.Rect(rect)
gyorgyf@5 146 ## dx = d/2. * math.cos(math.radians(angle))
gyorgyf@5 147 ## dy = d/2. * math.sin(math.radians(angle))
gyorgyf@5 148 ## rect.center = startpoint
gyorgyf@5 149 ## rect.move_ip(dx, dy)
gyorgyf@5 150 ## bigSurf.unlock()
gyorgyf@5 151 ##
gyorgyf@5 152 ## elif type=="circle":
gyorgyf@5 153 ## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha()
gyorgyf@5 154 ## bigSurf.fill((0,0,0,0))
gyorgyf@5 155 ## bigSurf.lock()
gyorgyf@5 156 ## for x in range(d, 0, -1):
gyorgyf@5 157 ## pygame.draw.circle(bigSurf, color.eval(x), (d,d), x)
gyorgyf@5 158 ## bigSurf.unlock()
gyorgyf@5 159 ## rect = bigSurf.get_rect()
gyorgyf@5 160 ## srect = pygame.Rect(rect)
gyorgyf@5 161 ## rect.center = (startpoint[0], startpoint[1])
gyorgyf@5 162 ##
gyorgyf@5 163 ## elif type=="rect":
gyorgyf@5 164 ## bigSurf = pygame.Surface((2*d, 2*d)).convert_alpha()
gyorgyf@5 165 ## bigSurf.fill((0,0,0,0))
gyorgyf@5 166 ## c = bigSurf.get_rect().center
gyorgyf@5 167 ## bigSurf.lock()
gyorgyf@5 168 ## for x in range(d,-1,-1):
gyorgyf@5 169 ## r = pygame.Rect(0,0,2*x,2*x)
gyorgyf@5 170 ## r.center = c
gyorgyf@5 171 ## pygame.draw.rect(bigSurf, color.eval(x), r)
gyorgyf@5 172 ## bigSurf.unlock()
gyorgyf@5 173 ## bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
gyorgyf@5 174 ## bigSurf.set_colorkey((0,0,0, 0))
gyorgyf@5 175 ##
gyorgyf@5 176 ## rect = bigSurf.get_rect()
gyorgyf@5 177 ## srect = pygame.Rect(rect)
gyorgyf@5 178 ## rect.center = startpoint
gyorgyf@5 179 ## else:
gyorgyf@5 180 ## raise NameError("type must be one of \"line\",\"circle\" or \"rect\"")
gyorgyf@5 181 ##
gyorgyf@5 182 ## if mode is None:
gyorgyf@5 183 ## surface.blit(bigSurf, rect, srect)
gyorgyf@5 184 ## else:
gyorgyf@5 185 ## if mode=="+":
gyorgyf@5 186 ## cf = pygame.color.add
gyorgyf@5 187 ## elif mode=="*":
gyorgyf@5 188 ## cf = pygame.color.multiply
gyorgyf@5 189 ## elif mode=="-":
gyorgyf@5 190 ## cf = pygame.color.subtract
gyorgyf@5 191 ## else:
gyorgyf@5 192 ## raise NameError("type must be one of \"+\", \"*\", \"-\" or None")
gyorgyf@5 193 ## irect = surface.get_clip().clip(rect)
gyorgyf@5 194 ## surface.lock()
gyorgyf@5 195 ## for x in range(irect.left, irect.left+irect.width):
gyorgyf@5 196 ## for y in range(irect.top, irect.top+irect.height):
gyorgyf@5 197 ## surface.set_at((x,y), cf(surface.get_at((x,y)), bigSurf.get_at((x-rect.left, y-rect.top)) ) )
gyorgyf@5 198 ## surface.unlock()
gyorgyf@5 199 ##
gyorgyf@5 200 ## del bigSurf
gyorgyf@5 201 ## char = pygame.Surface((d+1, 257))
gyorgyf@5 202 ### char.fill((0,0,0))
gyorgyf@5 203 ### ox = 0
gyorgyf@5 204 ### oldcol = color.eval(0)
gyorgyf@5 205 ### for x in range(d):
gyorgyf@5 206 ### col = color.eval(x)
gyorgyf@5 207 ### pygame.draw.line(char, (255,0,0), (x, 256-col[0]), (ox, 256-oldcol[0]))
gyorgyf@5 208 ### pygame.draw.line(char, (0,255,0), (x, 256-col[1]), (ox, 256-oldcol[1]))
gyorgyf@5 209 ### pygame.draw.line(char, (0,0,255), (x, 256-col[2]), (ox, 256-oldcol[2]))
gyorgyf@5 210 ### pygame.draw.line(char, (255,255,255), (x, 256-col[3]), (ox, 256-oldcol[3]))
gyorgyf@5 211 ### ox = x
gyorgyf@5 212 ### oldcol = col
gyorgyf@5 213 ###
gyorgyf@5 214 ## return char
gyorgyf@5 215
gyorgyf@5 216
gyorgyf@5 217
gyorgyf@5 218
gyorgyf@5 219 def vertical(size, startcolor, endcolor):
gyorgyf@5 220 """
gyorgyf@5 221 Draws a vertical linear gradient filling the entire surface. Returns a
gyorgyf@5 222 surface filled with the gradient (numeric is only 2-3 times faster).
gyorgyf@5 223 """
gyorgyf@5 224 height = size[1]
gyorgyf@5 225 bigSurf = pygame.Surface((1,height)).convert_alpha()
gyorgyf@5 226 dd = 1.0/height
gyorgyf@5 227 sr, sg, sb, sa = startcolor
gyorgyf@5 228 er, eg, eb, ea = endcolor
gyorgyf@5 229 rm = (er-sr)*dd
gyorgyf@5 230 gm = (eg-sg)*dd
gyorgyf@5 231 bm = (eb-sb)*dd
gyorgyf@5 232 am = (ea-sa)*dd
gyorgyf@5 233 for y in range(height):
gyorgyf@5 234 bigSurf.set_at((0,y),
gyorgyf@5 235 (int(sr + rm*y),
gyorgyf@5 236 int(sg + gm*y),
gyorgyf@5 237 int(sb + bm*y),
gyorgyf@5 238 int(sa + am*y))
gyorgyf@5 239 )
gyorgyf@5 240 return pygame.transform.scale(bigSurf, size)
gyorgyf@5 241
gyorgyf@5 242
gyorgyf@5 243 def horizontal(size, startcolor, endcolor):
gyorgyf@5 244 """
gyorgyf@5 245 Draws a horizontal linear gradient filling the entire surface. Returns a
gyorgyf@5 246 surface filled with the gradient (numeric is only 2-3 times faster).
gyorgyf@5 247 """
gyorgyf@5 248 width = size[0]
gyorgyf@5 249 bigSurf = pygame.Surface((width, 1)).convert_alpha()
gyorgyf@5 250 dd = 1.0/width
gyorgyf@5 251 sr, sg, sb, sa = startcolor
gyorgyf@5 252 er, eg, eb, ea = endcolor
gyorgyf@5 253 rm = (er-sr)*dd
gyorgyf@5 254 gm = (eg-sg)*dd
gyorgyf@5 255 bm = (eb-sb)*dd
gyorgyf@5 256 am = (ea-sa)*dd
gyorgyf@5 257 for y in range(width):
gyorgyf@5 258 bigSurf.set_at((y,0),
gyorgyf@5 259 (int(sr + rm*y),
gyorgyf@5 260 int(sg + gm*y),
gyorgyf@5 261 int(sb + bm*y),
gyorgyf@5 262 int(sa + am*y))
gyorgyf@5 263 )
gyorgyf@5 264 return pygame.transform.scale(bigSurf, size)
gyorgyf@5 265
gyorgyf@5 266
gyorgyf@5 267 def radial(radius, startcolor, endcolor):
gyorgyf@5 268 """
gyorgyf@5 269 Draws a linear raidal gradient on a square sized surface and returns
gyorgyf@5 270 that surface.
gyorgyf@5 271 """
gyorgyf@5 272 bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha()
gyorgyf@5 273 bigSurf.fill((0,0,0,0))
gyorgyf@5 274 dd = -1.0/radius
gyorgyf@5 275 sr, sg, sb, sa = endcolor
gyorgyf@5 276 er, eg, eb, ea = startcolor
gyorgyf@5 277 rm = (er-sr)*dd
gyorgyf@5 278 gm = (eg-sg)*dd
gyorgyf@5 279 bm = (eb-sb)*dd
gyorgyf@5 280 am = (ea-sa)*dd
gyorgyf@5 281
gyorgyf@5 282 draw_circle = pygame.draw.circle
gyorgyf@5 283 for rad in range(radius, 0, -1):
gyorgyf@5 284 draw_circle(bigSurf, (er + int(rm*rad),
gyorgyf@5 285 eg + int(gm*rad),
gyorgyf@5 286 eb + int(bm*rad),
gyorgyf@5 287 ea + int(am*rad)), (radius, radius), rad)
gyorgyf@5 288 return bigSurf
gyorgyf@5 289
gyorgyf@5 290 def squared(width, startcolor, endcolor):
gyorgyf@5 291 """
gyorgyf@5 292 Draws a linear sqared gradient on a square sized surface and returns
gyorgyf@5 293 that surface.
gyorgyf@5 294 """
gyorgyf@5 295 bigSurf = pygame.Surface((width, width)).convert_alpha()
gyorgyf@5 296 bigSurf.fill((0,0,0,0))
gyorgyf@5 297 dd = -1.0/(width/2)
gyorgyf@5 298 sr, sg, sb, sa = endcolor
gyorgyf@5 299 er, eg, eb, ea = startcolor
gyorgyf@5 300 rm = (er-sr)*dd
gyorgyf@5 301 gm = (eg-sg)*dd
gyorgyf@5 302 bm = (eb-sb)*dd
gyorgyf@5 303 am = (ea-sa)*dd
gyorgyf@5 304
gyorgyf@5 305 draw_rect = pygame.draw.rect
gyorgyf@5 306 for currentw in range((width/2), 0, -1):
gyorgyf@5 307 pos = (width/2)-currentw
gyorgyf@5 308 draw_rect(bigSurf, (er + int(rm*currentw),
gyorgyf@5 309 eg + int(gm*currentw),
gyorgyf@5 310 eb + int(bm*currentw),
gyorgyf@5 311 ea + int(am*currentw)), pygame.Rect(pos, pos, 2*currentw, 2*currentw ))
gyorgyf@5 312 return bigSurf
gyorgyf@5 313
gyorgyf@5 314
gyorgyf@5 315 def vertical_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)):
gyorgyf@5 316 """
gyorgyf@5 317 Draws a vertical linear gradient filling the entire surface. Returns a
gyorgyf@5 318 surface filled with the gradient (numeric is only 2x faster).
gyorgyf@5 319 Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define
gyorgyf@5 320 how the color changes.
gyorgyf@5 321 """
gyorgyf@5 322 height = size[1]
gyorgyf@5 323 bigSurf = pygame.Surface((1,height)).convert_alpha()
gyorgyf@5 324 color = ColorInterpolator(height, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 325 for y in range(0, height):
gyorgyf@5 326 bigSurf.set_at((0,y), color.eval(y+0.1))
gyorgyf@5 327 return pygame.transform.scale(bigSurf, size)
gyorgyf@5 328
gyorgyf@5 329
gyorgyf@5 330 def horizontal_func(size, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1)):
gyorgyf@5 331 """
gyorgyf@5 332 Draws a horizontal linear gradient filling the entire surface. Returns a
gyorgyf@5 333 surface filled with the gradient (numeric is only 2x faster).
gyorgyf@5 334 Rfunc, Gfunc, Bfunc and Afunc are function like y = f(x). They define
gyorgyf@5 335 how the color changes.
gyorgyf@5 336 """
gyorgyf@5 337 width = size[0]
gyorgyf@5 338 bigSurf = pygame.Surface((width, 1)).convert_alpha()
gyorgyf@5 339 color = ColorInterpolator(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 340 for y in range(0, width):
gyorgyf@5 341 bigSurf.set_at((y, 0), color.eval(y+0.1))
gyorgyf@5 342 return pygame.transform.scale(bigSurf, size)
gyorgyf@5 343
gyorgyf@5 344 def radial_func(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0)):
gyorgyf@5 345 """
gyorgyf@5 346 Draws a linear raidal gradient on a square sized surface and returns
gyorgyf@5 347 that surface.
gyorgyf@5 348 """
gyorgyf@5 349 bigSurf = pygame.Surface((2*radius, 2*radius)).convert_alpha()
gyorgyf@5 350 if len(colorkey)==3:
gyorgyf@5 351 colorkey += (0,)
gyorgyf@5 352 bigSurf.fill(colorkey)
gyorgyf@5 353 color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 354 draw_circle = pygame.draw.circle
gyorgyf@5 355 for rad in range(radius, 0, -1):
gyorgyf@5 356 draw_circle(bigSurf, color.eval(rad), (radius, radius), rad)
gyorgyf@5 357 return bigSurf
gyorgyf@5 358
gyorgyf@5 359 def radial_func_offset(radius, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), colorkey=(0,0,0,0), offset=(0,0)):
gyorgyf@5 360 """
gyorgyf@5 361 Draws a linear raidal gradient on a square sized surface and returns
gyorgyf@5 362 that surface.
gyorgyf@5 363 offset is the amount the center of the gradient is displaced of the center of the image.
gyorgyf@5 364 Unfotunately this function ignores alpha.
gyorgyf@5 365 """
gyorgyf@5 366 bigSurf = pygame.Surface((2*radius, 2*radius))#.convert_alpha()
gyorgyf@5 367
gyorgyf@5 368 mask = pygame.Surface((2*radius, 2*radius), pygame.SRCALPHA)#.convert_alpha()
gyorgyf@5 369 mask.fill(colorkey)
gyorgyf@5 370 mask.set_colorkey((255,0,255))
gyorgyf@5 371 pygame.draw.circle(mask, (255,0,255), (radius, radius), radius)
gyorgyf@5 372
gyorgyf@5 373 if len(colorkey)==3:
gyorgyf@5 374 colorkey += (0,)
gyorgyf@5 375 bigSurf.fill(colorkey)
gyorgyf@5 376
gyorgyf@5 377 color = ColorInterpolator(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 378 draw_circle = pygame.draw.circle
gyorgyf@5 379 radi = radius + int(math.hypot(offset[0], offset[1])+1)
gyorgyf@5 380 for rad in range(radi, 0, -1):
gyorgyf@5 381 draw_circle(bigSurf, color.eval(rad), (radius+offset[0], radius+offset[1]), rad)
gyorgyf@5 382
gyorgyf@5 383 bigSurf.blit(mask, (0,0))
gyorgyf@5 384 bigSurf.set_colorkey(colorkey)
gyorgyf@5 385 return bigSurf
gyorgyf@5 386
gyorgyf@5 387
gyorgyf@5 388 def squared_func(width, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), offset=(0,0)):
gyorgyf@5 389 """
gyorgyf@5 390 Draws a linear sqared gradient on a square sized surface and returns
gyorgyf@5 391 that surface.
gyorgyf@5 392 """
gyorgyf@5 393 bigSurf = pygame.Surface((width, width)).convert_alpha()
gyorgyf@5 394 bigSurf.fill((0,0,0,0))
gyorgyf@5 395 color = ColorInterpolator(width/2, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 396 draw_rect = pygame.draw.rect
gyorgyf@5 397 widthh = width+2*int(max(abs(offset[0]),abs(offset[1])))
gyorgyf@5 398 for currentw in range((widthh/2), 0, -1):
gyorgyf@5 399 ## pos = (width/2)-currentw
gyorgyf@5 400 rect = pygame.Rect(0, 0, 2*currentw, 2*currentw )
gyorgyf@5 401 rect.center = (width/2+offset[0], width/2+offset[1])
gyorgyf@5 402 draw_rect(bigSurf, color.eval(currentw), rect)
gyorgyf@5 403 return bigSurf
gyorgyf@5 404
gyorgyf@5 405 def draw_gradient(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
gyorgyf@5 406 """
gyorgyf@5 407 Instead of returning an Surface, this function draw it directy onto the
gyorgyf@5 408 given Surface and returns the rect.
gyorgyf@5 409 """
gyorgyf@5 410 dx = endpoint[0]-startpoint[0]
gyorgyf@5 411 dy = endpoint[1]-startpoint[1]
gyorgyf@5 412 d = int(round(math.hypot(dx, dy)))
gyorgyf@5 413 angle = math.degrees( math.atan2(dy, dx) )
gyorgyf@5 414
gyorgyf@5 415 h = int(2.*math.hypot(*surface.get_size()))
gyorgyf@5 416
gyorgyf@5 417 bigSurf = horizontal_func((d,h), startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 418
gyorgyf@5 419 ## bigSurf = pygame.transform.rotate(bigSurf, -angle) #rotozoom(bigSurf, -angle, 1)
gyorgyf@5 420 bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
gyorgyf@5 421 ## bigSurf.set_colorkey((0,0,0, 0))
gyorgyf@5 422 rect = bigSurf.get_rect()
gyorgyf@5 423 srect = pygame.Rect(rect)
gyorgyf@5 424 dx = d/2. * math.cos(math.radians(angle))
gyorgyf@5 425 dy = d/2. * math.sin(math.radians(angle))
gyorgyf@5 426 rect.center = startpoint
gyorgyf@5 427 rect.move_ip(dx, dy)
gyorgyf@5 428 if BLEND_MODES_AVAILABLE:
gyorgyf@5 429 return surface.blit(bigSurf, rect, None, mode)
gyorgyf@5 430 else:
gyorgyf@5 431 return surface.blit(bigSurf, rect)
gyorgyf@5 432
gyorgyf@5 433
gyorgyf@5 434 def draw_circle(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
gyorgyf@5 435 """
gyorgyf@5 436 Instead of returning an Surface, this function draw it directy onto the
gyorgyf@5 437 given Surface and returns the rect.
gyorgyf@5 438 """
gyorgyf@5 439 dx = endpoint[0]-startpoint[0]
gyorgyf@5 440 dy = endpoint[1]-startpoint[1]
gyorgyf@5 441 radius = int(round(math.hypot(dx, dy)))
gyorgyf@5 442 pos = (startpoint[0]-radius, startpoint[1]-radius)
gyorgyf@5 443 if BLEND_MODES_AVAILABLE:
gyorgyf@5 444 return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos, None, mode)
gyorgyf@5 445 else:
gyorgyf@5 446 return surface.blit(radial_func(radius, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc), pos)
gyorgyf@5 447
gyorgyf@5 448 def draw_squared(surface, startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), mode=0):
gyorgyf@5 449 """
gyorgyf@5 450 Instead of returning an Surface, this function draw it directy onto the
gyorgyf@5 451 given Surface and returns the rect.
gyorgyf@5 452 """
gyorgyf@5 453 dx = endpoint[0]-startpoint[0]
gyorgyf@5 454 dy = endpoint[1]-startpoint[1]
gyorgyf@5 455 angle = math.degrees( math.atan2(dy, dx) )
gyorgyf@5 456 width = 2*int(round(math.hypot(dx, dy)))
gyorgyf@5 457
gyorgyf@5 458 bigSurf = squared_func(width, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 459
gyorgyf@5 460 bigSurf = pygame.transform.rotozoom(bigSurf, -angle, 1)
gyorgyf@5 461 ## bigSurf.set_colorkey((0,0,0, 0))
gyorgyf@5 462 rect = bigSurf.get_rect()
gyorgyf@5 463 rect.center = startpoint
gyorgyf@5 464 if BLEND_MODES_AVAILABLE:
gyorgyf@5 465 return surface.blit(bigSurf, rect, None, mode)
gyorgyf@5 466 else:
gyorgyf@5 467 return surface.blit(bigSurf, rect)
gyorgyf@5 468
gyorgyf@5 469
gyorgyf@5 470 def chart(startpoint, endpoint, startcolor, endcolor, Rfunc = (lambda x:x), Gfunc = (lambda x:x), Bfunc = (lambda x:x), Afunc = (lambda x:1), scale=None):
gyorgyf@5 471 """
gyorgyf@5 472 This returns a Surface where the change of the colors over the distance
gyorgyf@5 473 (the width of the image) is showen as a line.
gyorgyf@5 474 scale: a float, 1 is not scaling
gyorgyf@5 475 """
gyorgyf@5 476 dx = endpoint[0]-startpoint[0]
gyorgyf@5 477 dy = endpoint[1]-startpoint[1]
gyorgyf@5 478 distance = int(round(math.hypot(dx, dy)))
gyorgyf@5 479 color = ColorInterpolator(distance, startcolor, endcolor, Rfunc, Gfunc, Bfunc, Afunc)
gyorgyf@5 480 bigSurf = pygame.Surface((distance, 256))
gyorgyf@5 481 bigSurf.fill((0,)*3)
gyorgyf@5 482 oldcol = color.eval(0)
gyorgyf@5 483 for x in range(distance):
gyorgyf@5 484 r, g, b, a = color.eval(x)
gyorgyf@5 485 pygame.draw.line(bigSurf, (255, 0, 0, 128), (x-1, oldcol[0]), (x, r))
gyorgyf@5 486 pygame.draw.line(bigSurf, (0, 255, 0, 128), (x-1, oldcol[1]), (x, g))
gyorgyf@5 487 pygame.draw.line(bigSurf, (0, 0, 255, 128), (x-1, oldcol[2]), (x, b))
gyorgyf@5 488 pygame.draw.line(bigSurf, (255, 255, 255, 128), (x-1, oldcol[3]), (x, a))
gyorgyf@5 489 oldcol = (r,g,b,a)
gyorgyf@5 490 if scale:
gyorgyf@5 491 ## return pygame.transform.scale(bigSurf, size)
gyorgyf@5 492 return pygame.transform.rotozoom(bigSurf, 0, scale)
gyorgyf@5 493 return pygame.transform.flip(bigSurf, 0, 1)
gyorgyf@5 494 #------------------------------------------------------------------------------
gyorgyf@5 495
gyorgyf@5 496
gyorgyf@5 497
gyorgyf@5 498
gyorgyf@5 499 def genericFxyGradient(surf, clip, color1, color2, func, intx, yint, zint=None):
gyorgyf@5 500 """
gyorgyf@5 501 genericFxyGradient(size, color1, color2,func, intx, yint, zint=None)
gyorgyf@5 502
gyorgyf@5 503 some sort of highfield drawer :-)
gyorgyf@5 504
gyorgyf@5 505 surf : surface to draw
gyorgyf@5 506 clip : rect on surf to draw in
gyorgyf@5 507 color1 : start color
gyorgyf@5 508 color2 : end color
gyorgyf@5 509 func : function z = func(x,y)
gyorgyf@5 510 xint : interval in x direction where the function is evaluated
gyorgyf@5 511 yint : interval in y direction where the function is evaluated
gyorgyf@5 512 zint : if not none same as yint or xint, if None then the max and min value
gyorgyf@5 513 of func is taken as z-interval
gyorgyf@5 514
gyorgyf@5 515 color = a*func(b*(x+c), d*(y+e))+f
gyorgyf@5 516 """
gyorgyf@5 517 # make shure that x1<x2 and y1<y2 and z1<z2
gyorgyf@5 518 w,h = clip.size
gyorgyf@5 519 x1 = min(intx)
gyorgyf@5 520 x2 = max(intx)
gyorgyf@5 521 y1 = min(yint)
gyorgyf@5 522 y2 = max(yint)
gyorgyf@5 523 if zint: # if user give us z intervall, then use it
gyorgyf@5 524 z1 = min(zint)
gyorgyf@5 525 z2 = max(zint)
gyorgyf@5 526 else: # look for extrema of function (not best algorithme)
gyorgyf@5 527 z1 = func(x1,y1)
gyorgyf@5 528 z2 = z1
gyorgyf@5 529 for i in range(w):
gyorgyf@5 530 for j in range(h):
gyorgyf@5 531 r = func(i,j)
gyorgyf@5 532 z1 = min(z1, r)
gyorgyf@5 533 z2 = max(z2, r)
gyorgyf@5 534
gyorgyf@5 535 x1 = float(x1)
gyorgyf@5 536 x2 = float(x2)
gyorgyf@5 537 y1 = float(y1)
gyorgyf@5 538 y2 = float(y2)
gyorgyf@5 539 z1 = float(z1)
gyorgyf@5 540 z2 = float(z2)
gyorgyf@5 541 if len(color1)==3:
gyorgyf@5 542 color1 = list(color1)
gyorgyf@5 543 color1.append(255)
gyorgyf@5 544 if len(color2)==3:
gyorgyf@5 545 color2 = list(color2)
gyorgyf@5 546 color2.append(255)
gyorgyf@5 547
gyorgyf@5 548 # calculate streching and displacement variables
gyorgyf@5 549 a = ((color2[0]-color1[0])/(z2-z1), \
gyorgyf@5 550 (color2[1]-color1[1])/(z2-z1), \
gyorgyf@5 551 (color2[2]-color1[2])/(z2-z1), \
gyorgyf@5 552 (color2[3]-color1[3])/(z2-z1) ) # streching in z direction
gyorgyf@5 553 b = (x2-x1)/float(w) # streching in x direction
gyorgyf@5 554 d = (y2-y1)/float(h) # streching in y direction
gyorgyf@5 555 f = ( color1[0]-a[0]*z1, \
gyorgyf@5 556 color1[1]-a[1]*z1, \
gyorgyf@5 557 color1[2]-a[2]*z1, \
gyorgyf@5 558 color1[3]-a[3]*z1 )# z displacement
gyorgyf@5 559 c = x1/b
gyorgyf@5 560 e = y1/d
gyorgyf@5 561
gyorgyf@5 562 surff = pygame.surface.Surface((w,h)).convert_alpha()
gyorgyf@5 563 # generate values
gyorgyf@5 564 for i in range(h):
gyorgyf@5 565 for j in range(w):
gyorgyf@5 566 val = func(b*(j+c), d*(i+e))
gyorgyf@5 567 #clip color
gyorgyf@5 568 color = ( max(min(a[0]*val+f[0],255),0), \
gyorgyf@5 569 max(min(a[1]*val+f[1],255),0), \
gyorgyf@5 570 max(min(a[2]*val+f[2],255),0), \
gyorgyf@5 571 max(min(a[3]*val+f[3],255),0) )
gyorgyf@5 572 surff.set_at( (j,i), color )
gyorgyf@5 573 surf.blit(surff, clip)
gyorgyf@5 574
gyorgyf@5 575
gyorgyf@5 576