From: simon Date: Sat, 28 Feb 2009 23:04:58 +0000 (+0000) Subject: Stop using physical tabs in Python. (I was goaded into doing this by X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/commitdiff_plain/0996dd4c856a3852a92cb7f17cf3fb78a286c075 Stop using physical tabs in Python. (I was goaded into doing this by my editor, which has defaulted to showing them as explicit ^I for a while now, but it seems like a generally prudent idea in any case.) git-svn-id: svn://svn.tartarus.org/sgt/putty@8472 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/icons/mkicon.py b/icons/mkicon.py index d40a9815..3e6d81c9 100755 --- a/icons/mkicon.py +++ b/icons/mkicon.py @@ -20,28 +20,28 @@ def overlay(src, x, y, dst): x = int(x) y = int(y) for (sx, sy), colour in src.items(): - dst[sx+x, sy+y] = blend(colour, dst.get((sx+x, sy+y), cT)) + dst[sx+x, sy+y] = blend(colour, dst.get((sx+x, sy+y), cT)) def finalise(canvas): for k in canvas.keys(): - canvas[k] = finalisepix(canvas[k]) + canvas[k] = finalisepix(canvas[k]) def bbox(canvas): minx, miny, maxx, maxy = None, None, None, None for (x, y) in canvas.keys(): - if minx == None: - minx, miny, maxx, maxy = x, y, x+1, y+1 - else: - minx = min(minx, x) - miny = min(miny, y) - maxx = max(maxx, x+1) - maxy = max(maxy, y+1) + if minx == None: + minx, miny, maxx, maxy = x, y, x+1, y+1 + else: + minx = min(minx, x) + miny = min(miny, y) + maxx = max(maxx, x+1) + maxy = max(maxy, y+1) return (minx, miny, maxx, maxy) def topy(canvas): miny = {} for (x, y) in canvas.keys(): - miny[x] = min(miny.get(x, y), y) + miny[x] = min(miny.get(x, y), y) return miny def render(canvas, minx, miny, maxx, maxy): @@ -49,10 +49,10 @@ def render(canvas, minx, miny, maxx, maxy): h = maxy - miny ret = [] for y in range(h): - ret.append([outpix(cT)] * w) + ret.append([outpix(cT)] * w) for (x, y), colour in canvas.items(): - if x >= minx and x < maxx and y >= miny and y < maxy: - ret[y-miny][x-minx] = outpix(colour) + if x >= minx and x < maxx and y >= miny and y < maxy: + ret[y-miny][x-minx] = outpix(colour) return ret # Code to actually draw pieces of icon. These don't generally worry @@ -63,7 +63,7 @@ def render(canvas, minx, miny, maxx, maxy): sqrthash = {} def memoisedsqrt(x): if not sqrthash.has_key(x): - sqrthash[x] = math.sqrt(x) + sqrthash[x] = math.sqrt(x) return sqrthash[x] BR, TR, BL, TL = range(4) # enumeration of quadrants for border() @@ -123,9 +123,9 @@ def border(canvas, thickness, squarecorners, out={}): thickness = memoisedsqrt(thickness) if thickness < 0.9: - darkness = 0.5 + darkness = 0.5 else: - darkness = 1 + darkness = 1 if thickness < 1: thickness = 1 thickness = round(thickness - 0.5) + 0.3 @@ -138,27 +138,27 @@ def border(canvas, thickness, squarecorners, out={}): squadrant = [[0] * (dmax+1) for x in range(dmax+1)] for x in range(dmax+1): - for y in range(dmax+1): - if max(x, y) < thickness: - squadrant[x][y] = darkness - if memoisedsqrt(x*x+y*y) < thickness: - cquadrant[x][y] = darkness + for y in range(dmax+1): + if max(x, y) < thickness: + squadrant[x][y] = darkness + if memoisedsqrt(x*x+y*y) < thickness: + cquadrant[x][y] = darkness bvalues = {} for (x, y), colour in canvas.items(): - for dx in range(-dmax, dmax+1): - for dy in range(-dmax, dmax+1): - quadrant = 2 * (dx < 0) + (dy < 0) - if (x, y, quadrant) in squarecorners: - bval = squadrant[abs(dx)][abs(dy)] - else: - bval = cquadrant[abs(dx)][abs(dy)] - if bvalues.get((x+dx,y+dy),0) < bval: - bvalues[(x+dx,y+dy)] = bval + for dx in range(-dmax, dmax+1): + for dy in range(-dmax, dmax+1): + quadrant = 2 * (dx < 0) + (dy < 0) + if (x, y, quadrant) in squarecorners: + bval = squadrant[abs(dx)][abs(dy)] + else: + bval = cquadrant[abs(dx)][abs(dy)] + if bvalues.get((x+dx,y+dy),0) < bval: + bvalues[(x+dx,y+dy)] = bval for (x, y), value in bvalues.items(): - if not canvas.has_key((x,y)): - canvas[(x,y)] = dark(value) + if not canvas.has_key((x,y)): + canvas[(x,y)] = dark(value) def sysbox(size, out={}): canvas = {} @@ -179,44 +179,44 @@ def sysbox(size, out={}): floppyrheight = 0.7 * size floppyheight = int(round(floppyrheight)) if floppyheight < 1: - floppyheight = 1 + floppyheight = 1 floppytop = floppybottom - floppyheight # The front panel is rectangular. for x in range(width): - for y in range(height): - grey = 3 - if x < highlight or y < highlight: - grey = grey + 1 - if x >= width-highlight or y >= height-bothighlight: - grey = grey - 1 - if y < highlight and x >= width-highlight: - v = (highlight-1-y) - (x-(width-highlight)) - if v < 0: - grey = grey - 1 - elif v > 0: - grey = grey + 1 - if y >= floppytop and y < floppybottom and \ - 2*x+2 > floppystart and 2*x < floppyend: - if 2*x >= floppystart and 2*x+2 <= floppyend and \ - floppyrheight >= 0.7: - grey = 0 - else: - grey = 2 - pixel(x, y, greypix(grey/4.0), canvas) + for y in range(height): + grey = 3 + if x < highlight or y < highlight: + grey = grey + 1 + if x >= width-highlight or y >= height-bothighlight: + grey = grey - 1 + if y < highlight and x >= width-highlight: + v = (highlight-1-y) - (x-(width-highlight)) + if v < 0: + grey = grey - 1 + elif v > 0: + grey = grey + 1 + if y >= floppytop and y < floppybottom and \ + 2*x+2 > floppystart and 2*x < floppyend: + if 2*x >= floppystart and 2*x+2 <= floppyend and \ + floppyrheight >= 0.7: + grey = 0 + else: + grey = 2 + pixel(x, y, greypix(grey/4.0), canvas) # The side panel is a parallelogram. for x in range(depth): - for y in range(height): - pixel(x+width, y-(x+1), greypix(0.5), canvas) + for y in range(height): + pixel(x+width, y-(x+1), greypix(0.5), canvas) # The top panel is another parallelogram. for x in range(width-1): - for y in range(depth): - grey = 3 - if x >= width-1 - highlight: - grey = grey + 1 - pixel(x+(y+1), -(y+1), greypix(grey/4.0), canvas) + for y in range(depth): + grey = 3 + if x >= width-1 - highlight: + grey = grey + 1 + pixel(x+(y+1), -(y+1), greypix(grey/4.0), canvas) # And draw a border. border(canvas, size, [], out) @@ -240,83 +240,83 @@ def monitor(size): # The front panel is rectangular. for x in range(width): - for y in range(height): - if x >= surround and y >= surround and \ - x < surround+swidth and y < surround+sheight: - # Screen. - sx = (float(x-surround) - swidth/3) / swidth - sy = (float(y-surround) - sheight/3) / sheight - shighlight = 1.0 - (sx*sx+sy*sy)*0.27 - pix = bluepix(shighlight) - if x < surround+shadow or y < surround+shadow: - pix = blend(cD, pix) # sharp-edged shadow on top and left - else: - # Complicated double bevel on the screen surround. - - # First, the outer bevel. We compute the distance - # from this pixel to each edge of the front - # rectangle. - list = [ - (x, +1), - (y, +1), - (width-1-x, -1), - (height-1-y, -1) - ] - # Now sort the list to find the distance to the - # _nearest_ edge, or the two joint nearest. - list.sort() - # If there's one nearest edge, that determines our - # bevel colour. If there are two joint nearest, our - # bevel colour is their shared one if they agree, - # and neutral otherwise. - outerbevel = 0 - if list[0][0] < list[1][0] or list[0][1] == list[1][1]: - if list[0][0] < highlight: - outerbevel = list[0][1] - - # Now, the inner bevel. We compute the distance - # from this pixel to each edge of the screen - # itself. - list = [ - (surround-1-x, -1), - (surround-1-y, -1), - (x-(surround+swidth), +1), - (y-(surround+sheight), +1) - ] - # Now we sort to find the _maximum_ distance, which - # conveniently ignores any less than zero. - list.sort() - # And now the strategy is pretty much the same as - # above, only we're working from the opposite end - # of the list. - innerbevel = 0 - if list[-1][0] > list[-2][0] or list[-1][1] == list[-2][1]: - if list[-1][0] >= 0 and list[-1][0] < highlight: - innerbevel = list[-1][1] - - # Now we know the adjustment we want to make to the - # pixel's overall grey shade due to the outer - # bevel, and due to the inner one. We break a tie - # in favour of a light outer bevel, but otherwise - # add. - grey = 3 - if outerbevel > 0 or outerbevel == innerbevel: - innerbevel = 0 - grey = grey + outerbevel + innerbevel - - pix = greypix(grey / 4.0) - - pixel(x, y, pix, canvas) + for y in range(height): + if x >= surround and y >= surround and \ + x < surround+swidth and y < surround+sheight: + # Screen. + sx = (float(x-surround) - swidth/3) / swidth + sy = (float(y-surround) - sheight/3) / sheight + shighlight = 1.0 - (sx*sx+sy*sy)*0.27 + pix = bluepix(shighlight) + if x < surround+shadow or y < surround+shadow: + pix = blend(cD, pix) # sharp-edged shadow on top and left + else: + # Complicated double bevel on the screen surround. + + # First, the outer bevel. We compute the distance + # from this pixel to each edge of the front + # rectangle. + list = [ + (x, +1), + (y, +1), + (width-1-x, -1), + (height-1-y, -1) + ] + # Now sort the list to find the distance to the + # _nearest_ edge, or the two joint nearest. + list.sort() + # If there's one nearest edge, that determines our + # bevel colour. If there are two joint nearest, our + # bevel colour is their shared one if they agree, + # and neutral otherwise. + outerbevel = 0 + if list[0][0] < list[1][0] or list[0][1] == list[1][1]: + if list[0][0] < highlight: + outerbevel = list[0][1] + + # Now, the inner bevel. We compute the distance + # from this pixel to each edge of the screen + # itself. + list = [ + (surround-1-x, -1), + (surround-1-y, -1), + (x-(surround+swidth), +1), + (y-(surround+sheight), +1) + ] + # Now we sort to find the _maximum_ distance, which + # conveniently ignores any less than zero. + list.sort() + # And now the strategy is pretty much the same as + # above, only we're working from the opposite end + # of the list. + innerbevel = 0 + if list[-1][0] > list[-2][0] or list[-1][1] == list[-2][1]: + if list[-1][0] >= 0 and list[-1][0] < highlight: + innerbevel = list[-1][1] + + # Now we know the adjustment we want to make to the + # pixel's overall grey shade due to the outer + # bevel, and due to the inner one. We break a tie + # in favour of a light outer bevel, but otherwise + # add. + grey = 3 + if outerbevel > 0 or outerbevel == innerbevel: + innerbevel = 0 + grey = grey + outerbevel + innerbevel + + pix = greypix(grey / 4.0) + + pixel(x, y, pix, canvas) # The side panel is a parallelogram. for x in range(depth): - for y in range(height): - pixel(x+width, y-x, greypix(0.5), canvas) + for y in range(height): + pixel(x+width, y-x, greypix(0.5), canvas) # The top panel is another parallelogram. for x in range(width): - for y in range(depth-1): - pixel(x+(y+1), -(y+1), greypix(0.75), canvas) + for y in range(depth-1): + pixel(x+(y+1), -(y+1), greypix(0.75), canvas) # And draw a border. border(canvas, size, [(0,int(height-1),BL)]) @@ -356,19 +356,19 @@ def lightning(size): innerx = round(7*size) for y in range(int(height)): - list = [] - if y <= outery: - list.append(width-1-int(outerx * float(y) / outery + 0.3)) - if y <= innery: - list.append(width-1-int(innerx * float(y) / innery + 0.3)) - y0 = height-1-y - if y0 <= outery: - list.append(int(outerx * float(y0) / outery + 0.3)) - if y0 <= innery: - list.append(int(innerx * float(y0) / innery + 0.3)) - list.sort() - for x in range(int(list[0]), int(list[-1]+1)): - pixel(x, y, cY, canvas) + list = [] + if y <= outery: + list.append(width-1-int(outerx * float(y) / outery + 0.3)) + if y <= innery: + list.append(width-1-int(innerx * float(y) / innery + 0.3)) + y0 = height-1-y + if y0 <= outery: + list.append(int(outerx * float(y0) / outery + 0.3)) + if y0 <= innery: + list.append(int(innerx * float(y0) / innery + 0.3)) + list.sort() + for x in range(int(list[0]), int(list[-1]+1)): + pixel(x, y, cY, canvas) # And draw a border. border(canvas, size, [(int(width-1),0,TR), (0,int(height-1),BL)]) @@ -392,37 +392,37 @@ def document(size): # Start by drawing a big white rectangle. for y in range(int(height)): - for x in range(int(width)): - pixel(x, y, cW, canvas) + for x in range(int(width)): + pixel(x, y, cW, canvas) # Now draw lines of text. for line in range(nlines): - # Decide where this line of text begins. - if line == 0: - start = round(4*size) - elif line < 5*nlines/7: - start = round((line - (nlines/7)) * size) - else: - start = round(1*size) - if start < round(1*size): - start = round(1*size) - # Decide where it ends. - endpoints = [10, 8, 11, 6, 5, 7, 5] - ey = line * 6.0 / (nlines-1) - eyf = math.floor(ey) - eyc = math.ceil(ey) - exf = endpoints[int(eyf)] - exc = endpoints[int(eyc)] - if eyf == eyc: - end = exf - else: - end = exf * (eyc-ey) + exc * (ey-eyf) - end = round(end * size) - - liney = height - (lineht+linespc) * (line+1) - for x in range(int(start), int(end)): - for y in range(int(lineht)): - pixel(x, y+liney, cK, canvas) + # Decide where this line of text begins. + if line == 0: + start = round(4*size) + elif line < 5*nlines/7: + start = round((line - (nlines/7)) * size) + else: + start = round(1*size) + if start < round(1*size): + start = round(1*size) + # Decide where it ends. + endpoints = [10, 8, 11, 6, 5, 7, 5] + ey = line * 6.0 / (nlines-1) + eyf = math.floor(ey) + eyc = math.ceil(ey) + exf = endpoints[int(eyf)] + exc = endpoints[int(eyc)] + if eyf == eyc: + end = exf + else: + end = exf * (eyc-ey) + exc * (ey-eyf) + end = round(end * size) + + liney = height - (lineht+linespc) * (line+1) + for x in range(int(start), int(end)): + for y in range(int(lineht)): + pixel(x, y+liney, cK, canvas) # And draw a border. border(canvas, size, \ @@ -450,37 +450,37 @@ def hat(size): brimbotc = round(10*size/3) for x in range(int(width)): - xs = float(x) * (len(topa)-1) / (width-1) - xf = math.floor(xs) - xc = math.ceil(xs) - topf = topa[int(xf)] - topc = topa[int(xc)] - if xf == xc: - top = topf - else: - top = topf * (xc-xs) + topc * (xs-xf) - top = math.floor(top) - bot = round(botl + (botr-botl) * x/(width-1)) - - for y in range(int(top), int(bot)): - pixel(x, y, cK, canvas) + xs = float(x) * (len(topa)-1) / (width-1) + xf = math.floor(xs) + xc = math.ceil(xs) + topf = topa[int(xf)] + topc = topa[int(xc)] + if xf == xc: + top = topf + else: + top = topf * (xc-xs) + topc * (xs-xf) + top = math.floor(top) + bot = round(botl + (botr-botl) * x/(width-1)) + + for y in range(int(top), int(bot)): + pixel(x, y, cK, canvas) # Now draw the brim. for x in range(int(width)): - brimtop = brimtopc + brimm * x - brimbot = brimbotc + brimm * x - for y in range(int(math.floor(brimtop)), int(math.ceil(brimbot))): - tophere = max(min(brimtop - y, 1), 0) - bothere = max(min(brimbot - y, 1), 0) - grey = bothere - tophere - # Only draw brim pixels over pixels which are (a) part - # of the main hat, and (b) not right on its edge. - if canvas.has_key((x,y)) and \ - canvas.has_key((x,y-1)) and \ - canvas.has_key((x,y+1)) and \ - canvas.has_key((x-1,y)) and \ - canvas.has_key((x+1,y)): - pixel(x, y, greypix(grey), canvas) + brimtop = brimtopc + brimm * x + brimbot = brimbotc + brimm * x + for y in range(int(math.floor(brimtop)), int(math.ceil(brimbot))): + tophere = max(min(brimtop - y, 1), 0) + bothere = max(min(brimbot - y, 1), 0) + grey = bothere - tophere + # Only draw brim pixels over pixels which are (a) part + # of the main hat, and (b) not right on its edge. + if canvas.has_key((x,y)) and \ + canvas.has_key((x,y-1)) and \ + canvas.has_key((x,y+1)) and \ + canvas.has_key((x-1,y)) and \ + canvas.has_key((x+1,y)): + pixel(x, y, greypix(grey), canvas) return canvas @@ -502,42 +502,42 @@ def key(size): # Ellipse for the key head, minus an off-centre circular hole. for y in range(int(keyheadh)): - dy = (y-(keyheadh-1)/2.0) / (keyheadh/2.0) - dyh = (y-(keyheadh-1)/2.0) / (keyholed/2.0) - for x in range(int(keyheadw)): - dx = (x-(keyheadw-1)/2.0) / (keyheadw/2.0) - dxh = (x-(keyheadw-1)/2.0-keyholeoff) / (keyholed/2.0) - if dy*dy+dx*dx <= 1 and dyh*dyh+dxh*dxh > 1: - pixel(x + keyshaftw, y, cy, canvas) + dy = (y-(keyheadh-1)/2.0) / (keyheadh/2.0) + dyh = (y-(keyheadh-1)/2.0) / (keyholed/2.0) + for x in range(int(keyheadw)): + dx = (x-(keyheadw-1)/2.0) / (keyheadw/2.0) + dxh = (x-(keyheadw-1)/2.0-keyholeoff) / (keyholed/2.0) + if dy*dy+dx*dx <= 1 and dyh*dyh+dxh*dxh > 1: + pixel(x + keyshaftw, y, cy, canvas) # Rectangle for the key shaft, extended at the bottom for the # key head detail. for x in range(int(keyshaftw)): - top = round((keyheadh - keyshafth) / 2) - bot = round((keyheadh + keyshafth) / 2) - xs = float(x) * (len(keyhead)-1) / round((len(keyhead)-1)*size) - xf = math.floor(xs) - xc = math.ceil(xs) - in_head = 0 - if xc < len(keyhead): - in_head = 1 - yf = keyhead[int(xf)] - yc = keyhead[int(xc)] - if xf == xc: - bot = yf - else: - bot = yf * (xc-xs) + yc * (xs-xf) - for y in range(int(top),int(bot)): - pixel(x, y, cy, canvas) - if in_head: - last = (x, y) - if x == 0: - squarepix.append((x, int(top), TL)) - if x == 0: - squarepix.append(last + (BL,)) - if last != None and not in_head: - squarepix.append(last + (BR,)) - last = None + top = round((keyheadh - keyshafth) / 2) + bot = round((keyheadh + keyshafth) / 2) + xs = float(x) * (len(keyhead)-1) / round((len(keyhead)-1)*size) + xf = math.floor(xs) + xc = math.ceil(xs) + in_head = 0 + if xc < len(keyhead): + in_head = 1 + yf = keyhead[int(xf)] + yc = keyhead[int(xc)] + if xf == xc: + bot = yf + else: + bot = yf * (xc-xs) + yc * (xs-xf) + for y in range(int(top),int(bot)): + pixel(x, y, cy, canvas) + if in_head: + last = (x, y) + if x == 0: + squarepix.append((x, int(top), TL)) + if x == 0: + squarepix.append(last + (BL,)) + if last != None and not in_head: + squarepix.append(last + (BR,)) + last = None # And draw a border. border(canvas, size, squarepix) @@ -554,28 +554,28 @@ def linedist(x1,y1, x2,y2, x,y): # Special case: if x1,y1 and x2,y2 are the same point, we # don't attempt to extrapolate it into a line at all. if x1 != x2 or y1 != y2: - # First, find the nearest point to x,y on the infinite - # projection of the line segment. So we construct a vector - # n perpendicular to that segment... - nx = y2-y1 - ny = x1-x2 - # ... compute the dot product of (x1,y1)-(x,y) with that - # vector... - nd = (x1-x)*nx + (y1-y)*ny - # ... multiply by the vector we first thought of... - ndx = nd * nx - ndy = nd * ny - # ... and divide twice by the length of n. - ndx = ndx / (nx*nx+ny*ny) - ndy = ndy / (nx*nx+ny*ny) - # That gives us a displacement vector from x,y to the - # nearest point. See if it's within the range of the line - # segment. - cx = x + ndx - cy = y + ndy - if cx >= min(x1,x2) and cx <= max(x1,x2) and \ - cy >= min(y1,y2) and cy <= max(y1,y2): - vectors.append((ndx,ndy)) + # First, find the nearest point to x,y on the infinite + # projection of the line segment. So we construct a vector + # n perpendicular to that segment... + nx = y2-y1 + ny = x1-x2 + # ... compute the dot product of (x1,y1)-(x,y) with that + # vector... + nd = (x1-x)*nx + (y1-y)*ny + # ... multiply by the vector we first thought of... + ndx = nd * nx + ndy = nd * ny + # ... and divide twice by the length of n. + ndx = ndx / (nx*nx+ny*ny) + ndy = ndy / (nx*nx+ny*ny) + # That gives us a displacement vector from x,y to the + # nearest point. See if it's within the range of the line + # segment. + cx = x + ndx + cy = y + ndy + if cx >= min(x1,x2) and cx <= max(x1,x2) and \ + cy >= min(y1,y2) and cy <= max(y1,y2): + vectors.append((ndx,ndy)) # Now we have up to three candidate result vectors: (ndx,ndy) # as computed just above, and the two vectors to the ends of @@ -584,10 +584,10 @@ def linedist(x1,y1, x2,y2, x,y): vectors = vectors + [(x1-x,y1-y), (x2-x,y2-y)] bestlen, best = None, None for v in vectors: - vlen = v[0]*v[0]+v[1]*v[1] - if bestlen == None or bestlen > vlen: - bestlen = vlen - best = v + vlen = v[0]*v[0]+v[1]*v[1] + if bestlen == None or bestlen > vlen: + bestlen = vlen + best = v return best def spanner(size): @@ -618,57 +618,57 @@ def spanner(size): ] for y in range(int(cmax)): - for x in range(int(cmax)): - vectors = [linedist(a,b,c,d,x,y) for ((a,b),(c,d)) in segments] - dists = [memoisedsqrt(vx*vx+vy*vy) for (vx,vy) in vectors] - - # If the distance to the hole line is less than - # holeradius, we're not part of the spanner. - if dists[0] < holeradius: - continue - # If the distance to the head `line' is less than - # headradius, we are part of the spanner; likewise if - # the distance to the shaft line is less than - # shaftwidth _and_ the resulting shaft point isn't - # beyond the shaft end. - if dists[1] > headradius and \ - (dists[2] > shaftwidth or x+vectors[2][0] >= shaftend): - continue - - # We're part of the spanner. Now compute the highlight - # on this pixel. We do this by computing a `slope - # vector', which points from this pixel in the - # direction of its nearest edge. We store an array of - # slope vectors, in polar coordinates. - angles = [math.atan2(vy,vx) for (vx,vy) in vectors] - slopes = [] - if dists[0] < holeradius + holehighlight: - slopes.append(((dists[0]-holeradius)/holehighlight,angles[0])) - if dists[1]/headradius < dists[2]/shaftwidth: - if dists[1] > headradius - headhighlight and dists[1] < headradius: - slopes.append(((headradius-dists[1])/headhighlight,math.pi+angles[1])) - else: - if dists[2] > shaftwidth - shafthighlight and dists[2] < shaftwidth: - slopes.append(((shaftwidth-dists[2])/shafthighlight,math.pi+angles[2])) - # Now we find the smallest distance in that array, if - # any, and that gives us a notional position on a - # sphere which we can use to compute the final - # highlight level. - bestdist = None - bestangle = 0 - for dist, angle in slopes: - if bestdist == None or bestdist > dist: - bestdist = dist - bestangle = angle - if bestdist == None: - bestdist = 1.0 - sx = (1.0-bestdist) * math.cos(bestangle) - sy = (1.0-bestdist) * math.sin(bestangle) - sz = math.sqrt(1.0 - sx*sx - sy*sy) - shade = sx-sy+sz / math.sqrt(3) # can range from -1 to +1 - shade = 1.0 - (1-shade)/3 - - pixel(x, y, yellowpix(shade), canvas) + for x in range(int(cmax)): + vectors = [linedist(a,b,c,d,x,y) for ((a,b),(c,d)) in segments] + dists = [memoisedsqrt(vx*vx+vy*vy) for (vx,vy) in vectors] + + # If the distance to the hole line is less than + # holeradius, we're not part of the spanner. + if dists[0] < holeradius: + continue + # If the distance to the head `line' is less than + # headradius, we are part of the spanner; likewise if + # the distance to the shaft line is less than + # shaftwidth _and_ the resulting shaft point isn't + # beyond the shaft end. + if dists[1] > headradius and \ + (dists[2] > shaftwidth or x+vectors[2][0] >= shaftend): + continue + + # We're part of the spanner. Now compute the highlight + # on this pixel. We do this by computing a `slope + # vector', which points from this pixel in the + # direction of its nearest edge. We store an array of + # slope vectors, in polar coordinates. + angles = [math.atan2(vy,vx) for (vx,vy) in vectors] + slopes = [] + if dists[0] < holeradius + holehighlight: + slopes.append(((dists[0]-holeradius)/holehighlight,angles[0])) + if dists[1]/headradius < dists[2]/shaftwidth: + if dists[1] > headradius - headhighlight and dists[1] < headradius: + slopes.append(((headradius-dists[1])/headhighlight,math.pi+angles[1])) + else: + if dists[2] > shaftwidth - shafthighlight and dists[2] < shaftwidth: + slopes.append(((shaftwidth-dists[2])/shafthighlight,math.pi+angles[2])) + # Now we find the smallest distance in that array, if + # any, and that gives us a notional position on a + # sphere which we can use to compute the final + # highlight level. + bestdist = None + bestangle = 0 + for dist, angle in slopes: + if bestdist == None or bestdist > dist: + bestdist = dist + bestangle = angle + if bestdist == None: + bestdist = 1.0 + sx = (1.0-bestdist) * math.cos(bestangle) + sy = (1.0-bestdist) * math.sin(bestangle) + sz = math.sqrt(1.0 - sx*sx - sy*sy) + shade = sx-sy+sz / math.sqrt(3) # can range from -1 to +1 + shade = 1.0 - (1-shade)/3 + + pixel(x, y, yellowpix(shade), canvas) # And draw a border. border(canvas, size, []) @@ -856,13 +856,13 @@ def pageant_icon(size): hty = topy(ht) yrelmin = None for cx in cty.keys(): - hx = cx - xrel - assert hty.has_key(hx) - yrel = cty[cx] - hty[hx] - if yrelmin == None: - yrelmin = yrel - else: - yrelmin = min(yrelmin, yrel) + hx = cx - xrel + assert hty.has_key(hx) + yrel = cty[cx] - hty[hx] + if yrelmin == None: + yrelmin = yrel + else: + yrelmin = min(yrelmin, yrel) # Overlay the hat on the computer. overlay(ht, xrel, yrelmin, c) @@ -882,27 +882,27 @@ import sys def testrun(func, fname): canvases = [] for size in [0.5, 0.6, 1.0, 1.2, 1.5, 4.0]: - canvases.append(func(size)) + canvases.append(func(size)) wid = 0 ht = 0 for canvas in canvases: - minx, miny, maxx, maxy = bbox(canvas) - wid = max(wid, maxx-minx+4) - ht = ht + maxy-miny+4 + minx, miny, maxx, maxy = bbox(canvas) + wid = max(wid, maxx-minx+4) + ht = ht + maxy-miny+4 block = [] for canvas in canvases: - minx, miny, maxx, maxy = bbox(canvas) - block.extend(render(canvas, minx-2, miny-2, minx-2+wid, maxy+2)) + minx, miny, maxx, maxy = bbox(canvas) + block.extend(render(canvas, minx-2, miny-2, minx-2+wid, maxy+2)) p = os.popen("convert -depth 8 -size %dx%d rgb:- %s" % (wid,ht,fname), "w") assert len(block) == ht for line in block: - assert len(line) == wid - for r, g, b, a in line: - # Composite on to orange. - r = int(round((r * a + 255 * (255-a)) / 255.0)) - g = int(round((g * a + 128 * (255-a)) / 255.0)) - b = int(round((b * a + 0 * (255-a)) / 255.0)) - p.write("%c%c%c" % (r,g,b)) + assert len(line) == wid + for r, g, b, a in line: + # Composite on to orange. + r = int(round((r * a + 255 * (255-a)) / 255.0)) + g = int(round((g * a + 128 * (255-a)) / 255.0)) + b = int(round((b * a + 0 * (255-a)) / 255.0)) + p.write("%c%c%c" % (r,g,b)) p.close() def drawicon(func, width, fname, orangebackground = 0): @@ -915,15 +915,15 @@ def drawicon(func, width, fname, orangebackground = 0): p = os.popen("convert -depth 8 -size %dx%d rgba:- %s" % (width,width,fname), "w") assert len(block) == width for line in block: - assert len(line) == width - for r, g, b, a in line: - if orangebackground: - # Composite on to orange. - r = int(round((r * a + 255 * (255-a)) / 255.0)) - g = int(round((g * a + 128 * (255-a)) / 255.0)) - b = int(round((b * a + 0 * (255-a)) / 255.0)) - a = 255 - p.write("%c%c%c%c" % (r,g,b,a)) + assert len(line) == width + for r, g, b, a in line: + if orangebackground: + # Composite on to orange. + r = int(round((r * a + 255 * (255-a)) / 255.0)) + g = int(round((g * a + 128 * (255-a)) / 255.0)) + b = int(round((b * a + 0 * (255-a)) / 255.0)) + a = 255 + p.write("%c%c%c%c" % (r,g,b,a)) p.close() args = sys.argv[1:] @@ -935,21 +935,21 @@ doingargs = 1 realargs = [] for arg in args: if doingargs and arg[0] == "-": - if arg == "-t": - test = 1 - elif arg == "-it": - orangebackground = 1 - elif arg == "-2": - colours = 0 - elif arg == "-T": - colours = 2 - elif arg == "--": - doingargs = 0 - else: - sys.stderr.write("unrecognised option '%s'\n" % arg) - sys.exit(1) + if arg == "-t": + test = 1 + elif arg == "-it": + orangebackground = 1 + elif arg == "-2": + colours = 0 + elif arg == "-T": + colours = 2 + elif arg == "--": + doingargs = 0 + else: + sys.stderr.write("unrecognised option '%s'\n" % arg) + sys.exit(1) else: - realargs.append(arg) + realargs.append(arg) if colours == 0: # Monochrome. @@ -957,27 +957,27 @@ if colours == 0: cY=cy=cW = 1 cT = -1 def greypix(value): - return [cK,cW][int(round(value))] + return [cK,cW][int(round(value))] def yellowpix(value): - return [cK,cW][int(round(value))] + return [cK,cW][int(round(value))] def bluepix(value): - return cK + return cK def dark(value): - return [cT,cK][int(round(value))] + return [cT,cK][int(round(value))] def blend(col1, col2): - if col1 == cT: - return col2 - else: - return col1 + if col1 == cT: + return col2 + else: + return col1 pixvals = [ (0x00, 0x00, 0x00, 0xFF), # cK (0xFF, 0xFF, 0xFF, 0xFF), # cW (0x00, 0x00, 0x00, 0x00), # cT ] def outpix(colour): - return pixvals[colour] + return pixvals[colour] def finalisepix(colour): - return colour + return colour def halftone(col1, col2): return (col1, col2) elif colours == 1: @@ -986,20 +986,20 @@ elif colours == 1: cT = -1 cD = -2 # special translucent half-darkening value used internally def greypix(value): - return [cK,cw,cw,cP,cW][int(round(4*value))] + return [cK,cw,cw,cP,cW][int(round(4*value))] def yellowpix(value): - return [cK,cy,cY][int(round(2*value))] + return [cK,cy,cY][int(round(2*value))] def bluepix(value): - return [cK,cb,cB][int(round(2*value))] + return [cK,cb,cB][int(round(2*value))] def dark(value): - return [cT,cD,cK][int(round(2*value))] + return [cT,cD,cK][int(round(2*value))] def blend(col1, col2): - if col1 == cT: - return col2 - elif col1 == cD: - return [cK,cK,cK,cK,cK,cK,cK,cw,cK,cr,cg,cy,cb,cm,cc,cw,cD,cD][col2] - else: - return col1 + if col1 == cT: + return col2 + elif col1 == cD: + return [cK,cK,cK,cK,cK,cK,cK,cw,cK,cr,cg,cy,cb,cm,cc,cw,cD,cD][col2] + else: + return col1 pixvals = [ (0x00, 0x00, 0x00, 0xFF), # cK (0x80, 0x00, 0x00, 0xFF), # cr @@ -1021,12 +1021,12 @@ elif colours == 1: (0x00, 0x00, 0x00, 0x00), # cT ] def outpix(colour): - return pixvals[colour] + return pixvals[colour] def finalisepix(colour): - # cD is used internally, but can't be output. Convert to cK. - if colour == cD: - return cK - return colour + # cD is used internally, but can't be output. Convert to cK. + if colour == cD: + return cK + return colour def halftone(col1, col2): return (col1, col2) else: @@ -1050,40 +1050,40 @@ else: cD = (0x00, 0x00, 0x00, 0x80) cT = (0x00, 0x00, 0x00, 0x00) def greypix(value): - value = max(min(value, 1), 0) - return (int(round(0xFF*value)),) * 3 + (0xFF,) + value = max(min(value, 1), 0) + return (int(round(0xFF*value)),) * 3 + (0xFF,) def yellowpix(value): - value = max(min(value, 1), 0) - return (int(round(0xFF*value)),) * 2 + (0, 0xFF) + value = max(min(value, 1), 0) + return (int(round(0xFF*value)),) * 2 + (0, 0xFF) def bluepix(value): - value = max(min(value, 1), 0) - return (0, 0, int(round(0xFF*value)), 0xFF) + value = max(min(value, 1), 0) + return (0, 0, int(round(0xFF*value)), 0xFF) def dark(value): - value = max(min(value, 1), 0) - return (0, 0, 0, int(round(0xFF*value))) + value = max(min(value, 1), 0) + return (0, 0, 0, int(round(0xFF*value))) def blend(col1, col2): - r1,g1,b1,a1 = col1 - r2,g2,b2,a2 = col2 - r = int(round((r1*a1 + r2*(0xFF-a1)) / 255.0)) - g = int(round((g1*a1 + g2*(0xFF-a1)) / 255.0)) - b = int(round((b1*a1 + b2*(0xFF-a1)) / 255.0)) - a = int(round((255*a1 + a2*(0xFF-a1)) / 255.0)) - return r, g, b, a + r1,g1,b1,a1 = col1 + r2,g2,b2,a2 = col2 + r = int(round((r1*a1 + r2*(0xFF-a1)) / 255.0)) + g = int(round((g1*a1 + g2*(0xFF-a1)) / 255.0)) + b = int(round((b1*a1 + b2*(0xFF-a1)) / 255.0)) + a = int(round((255*a1 + a2*(0xFF-a1)) / 255.0)) + return r, g, b, a def outpix(colour): - return colour + return colour if colours == 2: - # True colour with no alpha blending: we still have to - # finalise half-dark pixels to black. - def finalisepix(colour): - if colour[3] > 0: - return colour[:3] + (0xFF,) - return colour + # True colour with no alpha blending: we still have to + # finalise half-dark pixels to black. + def finalisepix(colour): + if colour[3] > 0: + return colour[:3] + (0xFF,) + return colour else: - def finalisepix(colour): - return colour + def finalisepix(colour): + return colour def halftone(col1, col2): - r1,g1,b1,a1 = col1 - r2,g2,b2,a2 = col2 + r1,g1,b1,a1 = col1 + r2,g2,b2,a2 = col2 colret = (int(r1+r2)/2, int(g1+g2)/2, int(b1+b2)/2, int(a1+a2)/2) return (colret, colret)