/doc/*.hhk
/doc/licence.but
/doc/copy.but
+/icons/*.pam
/icons/*.png
/icons/*.ico
/icons/*.icns
MODE = # override to -it on command line for opaque testing
-PNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).png))
-MONOPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.png))
-TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png))
+PAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).pam))
+MONOPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.pam))
+TRUEPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.pam))
+
+PNGS = $(patsubst %.pam,%.png,$(PAMS))
+MONOPNGS = $(patsubst %.pam,%.png,$(MONOPAMS))
+TRUEPNGS = $(patsubst %.pam,%.png,$(TRUEPAMS))
ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \
puttyins.ico
cp $(ICOS) ../windows
cp $(CICONS) ../unix
-$(PNGS): %.png: mkicon.py
+$(PAMS): %.pam: mkicon.py
./mkicon.py $(MODE) $(join $(subst -, ,$(basename $@)),_icon) $@
-$(MONOPNGS): %.png: mkicon.py
+$(PNGS) $(MONOPNGS) $(TRUEPNGS): %.png: %.pam
+ convert $< $@
+
+$(MONOPAMS): %.pam: mkicon.py
./mkicon.py -2 $(MODE) $(join $(subst -, ,$(subst -mono,,$(basename $@))),_icon) $@
-$(TRUEPNGS): %.png: mkicon.py
+$(TRUEPAMS): %.pam: mkicon.py
./mkicon.py -T $(MODE) $(join $(subst -, ,$(subst -true,,$(basename $@))),_icon) $@
putty.ico: putty-16.png putty-32.png putty-48.png \
xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png
./cicon.pl cfg_icon $^ > $@
-PuTTY.icns: putty-16-mono.png putty-16.png \
- putty-32-mono.png putty-32.png \
- putty-48-mono.png putty-48.png \
- putty-128.png
- ./macicon.py mono:putty-16-mono.png colour:putty-16.png \
- mono:putty-32-mono.png colour:putty-32.png \
- mono:putty-48-mono.png colour:putty-48.png \
- colour:putty-128.png \
+PuTTY.icns: putty-16-mono.pam putty-16.pam \
+ putty-32-mono.pam putty-32.pam \
+ putty-48-mono.pam putty-48.pam \
+ putty-128.pam
+ ./macicon.py mono:putty-16-mono.pam colour:putty-16.pam \
+ mono:putty-32-mono.pam colour:putty-32.pam \
+ mono:putty-48-mono.pam colour:putty-48.pam \
+ colour:putty-128.pam \
output:$@
clean:
- rm -f *.png *.ico *.icns *.c
+ rm -f *.pam *.png *.ico *.icns *.c
# Load an image file from disk and turn it into a simple list of
# 4-tuples giving 8-bit R,G,B,A values for each pixel.
#
-# My icon-building makefile already depends on ImageMagick, so I use
-# identify and convert here in place of more sensible Python libraries
-# so as to add no build dependency that wasn't already needed.
+# To avoid adding any build dependency on ImageMagick or Python
+# imaging libraries, none of which comes as standard on OS X, I insist
+# here that the file is in RGBA .pam format (as mkicon.py will have
+# generated it).
def load_rgba(filename):
- size = subprocess.check_output(["identify", "-format", "%wx%h", filename])
- width, height = map(int, size.split("x"))
- assert width == height
- data = subprocess.check_output(["convert", "-depth", "8",
- filename, "rgba:-"])
- assert len(data) == width*height*4
- rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)]
- return width, rgba
+ with open(filename) as f:
+ assert f.readline() == "P7\n"
+ for line in iter(f.readline, ''):
+ words = line.rstrip("\n").split()
+ if words[0] == "WIDTH":
+ width = int(words[1])
+ elif words[0] == "HEIGHT":
+ height = int(words[1])
+ elif words[0] == "DEPTH":
+ assert int(words[1]) == 4
+ elif words[0] == "TUPLTYPE":
+ assert words[1] == "RGB_ALPHA"
+ elif words[0] == "ENDHDR":
+ break
+
+ assert width == height
+ data = f.read()
+ assert len(data) == width*height*4
+ rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)]
+ return width, rgba
data = ""
for canvas in canvases:
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))
- p.close()
+ with open(fname, "w") as f:
+ f.write(("P7\nWIDTH %d\nHEIGHT %d\nDEPTH 3\nMAXVAL 255\n" +
+ "TUPLTYPE RGB\nENDHDR\n") % (wid, ht))
+ 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))
+ f.write("%c%c%c" % (r,g,b))
def drawicon(func, width, fname, orangebackground = 0):
canvas = func(width / 32.0)
assert minx >= 0 and miny >= 0 and maxx <= width and maxy <= width
block = render(canvas, 0, 0, width, width)
- 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))
- p.close()
+ with open(fname, "w") as f:
+ f.write(("P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\n" +
+ "TUPLTYPE RGB_ALPHA\nENDHDR\n") % (width, width))
+ 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
+ f.write("%c%c%c%c" % (r,g,b,a))
args = sys.argv[1:]