⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkicon.py

📁 putty
💻 PY
📖 第 1 页 / 共 3 页
字号:
#!/usr/bin/env python

import math

# Python code which draws the PuTTY icon components at a range of
# sizes.

# TODO
# ----
#
#  - use of alpha blending
#     + try for variable-transparency borders
#
#  - can we integrate the Mac icons into all this? Do we want to?

def pixel(x, y, colour, canvas):
    canvas[(int(x),int(y))] = colour

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))

def finalise(canvas):
    for k in canvas.keys():
	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)
    return (minx, miny, maxx, maxy)

def topy(canvas):
    miny = {}
    for (x, y) in canvas.keys():
	miny[x] = min(miny.get(x, y), y)
    return miny

def render(canvas, minx, miny, maxx, maxy):
    w = maxx - minx
    h = maxy - miny
    ret = []
    for y in range(h):
	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)
    return ret

# Code to actually draw pieces of icon. These don't generally worry
# about positioning within a canvas; they just draw at a standard
# location, return some useful coordinates, and leave composition
# to other pieces of code.

sqrthash = {}
def memoisedsqrt(x):
    if not sqrthash.has_key(x):
	sqrthash[x] = math.sqrt(x)
    return sqrthash[x]

BR, TR, BL, TL = range(4) # enumeration of quadrants for border()

def border(canvas, thickness, squarecorners, out={}):
    # I haven't yet worked out exactly how to do borders in a
    # properly alpha-blended fashion.
    #
    # When you have two shades of dark available (half-dark H and
    # full-dark F), the right sequence of circular border sections
    # around a pixel x starts off with these two layouts:
    #
    #   H    F
    #  HxH  FxF
    #   H    F
    #
    # Where it goes after that I'm not entirely sure, but I'm
    # absolutely sure those are the right places to start. However,
    # every automated algorithm I've tried has always started off
    # with the two layouts
    #
    #   H   HHH
    #  HxH  HxH
    #   H   HHH
    #
    # which looks much worse. This is true whether you do
    # pixel-centre sampling (define an inner circle and an outer
    # circle with radii differing by 1, set any pixel whose centre
    # is inside the inner circle to F, any pixel whose centre is
    # outside the outer one to nothing, interpolate between the two
    # and round sensibly), _or_ whether you plot a notional circle
    # of a given radius and measure the actual _proportion_ of each
    # pixel square taken up by it.
    #
    # It's not clear what I should be doing to prevent this. One
    # option is to attempt error-diffusion: Ian Jackson proved on
    # paper that if you round each pixel's ideal value to the
    # nearest of the available output values, then measure the
    # error at each pixel, propagate that error outwards into the
    # original values of the surrounding pixels, and re-round
    # everything, you do get the correct second stage. However, I
    # haven't tried it at a proper range of radii.
    #
    # Another option is that the automated mechanisms described
    # above would be entirely adequate if it weren't for the fact
    # that the human visual centres are adapted to detect
    # horizontal and vertical lines in particular, so the only
    # place you have to behave a bit differently is at the ends of
    # the top and bottom row of pixels in the circle, and the top
    # and bottom of the extreme columns.
    #
    # For the moment, what I have below is a very simple mechanism
    # which always uses only one alpha level for any given border
    # thickness, and which seems to work well enough for Windows
    # 16-colour icons. Everything else will have to wait.

    thickness = memoisedsqrt(thickness)

    if thickness < 0.9:
	darkness = 0.5
    else:
	darkness = 1
    if thickness < 1: thickness = 1
    thickness = round(thickness - 0.5) + 0.3

    out["borderthickness"] = thickness

    dmax = int(round(thickness))
    if dmax < thickness: dmax = dmax + 1

    cquadrant = [[0] * (dmax+1) for x in range(dmax+1)]
    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

    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 (x, y), value in bvalues.items():
	if not canvas.has_key((x,y)):
	    canvas[(x,y)] = dark(value)

def sysbox(size, out={}):
    canvas = {}

    # The system box of the computer.

    height = int(round(3.6*size))
    width = int(round(16.51*size))
    depth = int(round(2*size))
    highlight = int(round(1*size))
    bothighlight = int(round(1*size))

    out["sysboxheight"] = height

    floppystart = int(round(19*size)) # measured in half-pixels
    floppyend = int(round(29*size)) # measured in half-pixels
    floppybottom = height - bothighlight
    floppyrheight = 0.7 * size
    floppyheight = int(round(floppyrheight))
    if 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)

    # 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)

    # 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)

    # And draw a border.
    border(canvas, size, [], out)

    return canvas

def monitor(size):
    canvas = {}

    # The computer's monitor.

    height = int(round(9.55*size))
    width = int(round(11.49*size))
    surround = int(round(1*size))
    botsurround = int(round(2*size))
    sheight = height - surround - botsurround
    swidth = width - 2*surround
    depth = int(round(2*size))
    highlight = int(round(math.sqrt(size)))
    shadow = int(round(0.55*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)

    # 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)

    # 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)

    # And draw a border.
    border(canvas, size, [(0,int(height-1),BL)])

    return canvas

def computer(size):
    # Monitor plus sysbox.
    out = {}
    m = monitor(size)
    s = sysbox(size, out)
    x = int(round((2+size/(size+1))*size))
    y = int(out["sysboxheight"] + out["borderthickness"])
    mb = bbox(m)
    sb = bbox(s)
    xoff = sb[0] - mb[0] + x
    yoff = sb[3] - mb[3] - y
    overlay(m, xoff, yoff, s)
    return s

def lightning(size):
    canvas = {}

    # The lightning bolt motif.

    # We always want this to be an even number of pixels in height,
    # and an odd number in width.
    width = round(7*size) * 2 - 1
    height = round(8*size) * 2

    # The outer edge of each side of the bolt goes to this point.
    outery = round(8.4*size)
    outerx = round(11*size)

    # And the inner edge goes to this point.
    innery = height - 1 - outery
    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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -