1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Use NetPBM .pam as an intermediate format in the icon makefile.

mkicon.py now outputs .pam by hand, rather than using ImageMagick to
go straight to .png. For most purposes the main makefile then uses
ImageMagick anyway, to convert those .pams straight to the .pngs that
the rest of the scripts were expecting. But one script that doesn't do
that is macicon.py, which builds the MacOS .icns file by directly
reading those .pam files back in.

This allows the 'make icns' target in the icons directory to build
from a clean checkout on vanilla MacOS, without requiring a user to
install ImageMagick or any other non-core Python image handling
module.

(I could probably take this change at least a little bit further. I
don't see any reason why icon.pl - generating the Windows .ico files -
couldn't read the .pam files directly, about as easily as macicon.py
did, if anyone had a use case for building the Windows icons in the
presence of Python and Perl but in the absence of ImageMagick. But the
.png files are directly useful outputs for Unix, so _some_ PNG-writing
will have to remain here.)
This commit is contained in:
Simon Tatham 2016-03-23 06:41:27 +00:00
parent eac66b0281
commit 450a995f05
4 changed files with 73 additions and 50 deletions

1
.gitignore vendored
View File

@ -83,6 +83,7 @@
/doc/*.hhk /doc/*.hhk
/doc/licence.but /doc/licence.but
/doc/copy.but /doc/copy.but
/icons/*.pam
/icons/*.png /icons/*.png
/icons/*.ico /icons/*.ico
/icons/*.icns /icons/*.icns

View File

@ -5,9 +5,13 @@ SIZES = 16 32 48 128
MODE = # override to -it on command line for opaque testing MODE = # override to -it on command line for opaque testing
PNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).png)) PAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).pam))
MONOPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.png)) MONOPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.pam))
TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png)) 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 \ ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \
puttyins.ico puttyins.ico
@ -30,13 +34,16 @@ install: icos cicons
cp $(ICOS) ../windows cp $(ICOS) ../windows
cp $(CICONS) ../unix cp $(CICONS) ../unix
$(PNGS): %.png: mkicon.py $(PAMS): %.pam: mkicon.py
./mkicon.py $(MODE) $(join $(subst -, ,$(basename $@)),_icon) $@ ./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) $@ ./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) $@ ./mkicon.py -T $(MODE) $(join $(subst -, ,$(subst -true,,$(basename $@))),_icon) $@
putty.ico: putty-16.png putty-32.png putty-48.png \ putty.ico: putty-16.png putty-32.png putty-48.png \
@ -90,15 +97,15 @@ xpmpterm.c: pterm-16.png pterm-32.png pterm-48.png
xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png
./cicon.pl cfg_icon $^ > $@ ./cicon.pl cfg_icon $^ > $@
PuTTY.icns: putty-16-mono.png putty-16.png \ PuTTY.icns: putty-16-mono.pam putty-16.pam \
putty-32-mono.png putty-32.png \ putty-32-mono.pam putty-32.pam \
putty-48-mono.png putty-48.png \ putty-48-mono.pam putty-48.pam \
putty-128.png putty-128.pam
./macicon.py mono:putty-16-mono.png colour:putty-16.png \ ./macicon.py mono:putty-16-mono.pam colour:putty-16.pam \
mono:putty-32-mono.png colour:putty-32.png \ mono:putty-32-mono.pam colour:putty-32.pam \
mono:putty-48-mono.png colour:putty-48.png \ mono:putty-48-mono.pam colour:putty-48.pam \
colour:putty-128.png \ colour:putty-128.pam \
output:$@ output:$@
clean: clean:
rm -f *.png *.ico *.icns *.c rm -f *.pam *.png *.ico *.icns *.c

View File

@ -112,15 +112,28 @@ def make_colour_icon(size, rgba):
# Load an image file from disk and turn it into a simple list of # 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. # 4-tuples giving 8-bit R,G,B,A values for each pixel.
# #
# My icon-building makefile already depends on ImageMagick, so I use # To avoid adding any build dependency on ImageMagick or Python
# identify and convert here in place of more sensible Python libraries # imaging libraries, none of which comes as standard on OS X, I insist
# so as to add no build dependency that wasn't already needed. # here that the file is in RGBA .pam format (as mkicon.py will have
# generated it).
def load_rgba(filename): def load_rgba(filename):
size = subprocess.check_output(["identify", "-format", "%wx%h", filename]) with open(filename) as f:
width, height = map(int, size.split("x")) 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 assert width == height
data = subprocess.check_output(["convert", "-depth", "8", data = f.read()
filename, "rgba:-"])
assert len(data) == width*height*4 assert len(data) == width*height*4
rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)] rgba = [map(ord, data[i:i+4]) for i in range(0, len(data), 4)]
return width, rgba return width, rgba

View File

@ -893,7 +893,9 @@ def testrun(func, fname):
for canvas in canvases: for canvas in canvases:
minx, miny, maxx, maxy = bbox(canvas) minx, miny, maxx, maxy = bbox(canvas)
block.extend(render(canvas, minx-2, miny-2, minx-2+wid, maxy+2)) 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") 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 assert len(block) == ht
for line in block: for line in block:
assert len(line) == wid assert len(line) == wid
@ -902,8 +904,7 @@ def testrun(func, fname):
r = int(round((r * a + 255 * (255-a)) / 255.0)) r = int(round((r * a + 255 * (255-a)) / 255.0))
g = int(round((g * a + 128 * (255-a)) / 255.0)) g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0)) b = int(round((b * a + 0 * (255-a)) / 255.0))
p.write("%c%c%c" % (r,g,b)) f.write("%c%c%c" % (r,g,b))
p.close()
def drawicon(func, width, fname, orangebackground = 0): def drawicon(func, width, fname, orangebackground = 0):
canvas = func(width / 32.0) canvas = func(width / 32.0)
@ -912,7 +913,9 @@ def drawicon(func, width, fname, orangebackground = 0):
assert minx >= 0 and miny >= 0 and maxx <= width and maxy <= width assert minx >= 0 and miny >= 0 and maxx <= width and maxy <= width
block = render(canvas, 0, 0, width, width) block = render(canvas, 0, 0, width, width)
p = os.popen("convert -depth 8 -size %dx%d rgba:- %s" % (width,width,fname), "w") 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 assert len(block) == width
for line in block: for line in block:
assert len(line) == width assert len(line) == width
@ -923,8 +926,7 @@ def drawicon(func, width, fname, orangebackground = 0):
g = int(round((g * a + 128 * (255-a)) / 255.0)) g = int(round((g * a + 128 * (255-a)) / 255.0))
b = int(round((b * a + 0 * (255-a)) / 255.0)) b = int(round((b * a + 0 * (255-a)) / 255.0))
a = 255 a = 255
p.write("%c%c%c%c" % (r,g,b,a)) f.write("%c%c%c%c" % (r,g,b,a))
p.close()
args = sys.argv[1:] args = sys.argv[1:]