diff --git a/icons/Makefile b/icons/Makefile index ceb90e52..3aa7ef46 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -14,6 +14,7 @@ MONOPNGS = $(patsubst %.pam,%.png,$(MONOPAMS)) TRUEPNGS = $(patsubst %.pam,%.png,$(TRUEPAMS)) SVGS = $(patsubst %,%.svg,$(ICONS)) +MONOSVGS = $(patsubst %,%-mono.svg,$(ICONS)) ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \ puttyins.ico pterm.ico ptermcfg.ico @@ -22,12 +23,13 @@ CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c base: icos cicons -all: pngs monopngs base icns svgs truepngs +all: pngs monopngs base icns svgs monosvgs truepngs pngs: $(PNGS) monopngs: $(MONOPNGS) truepngs: $(TRUEPNGS) svgs: $(SVGS) +monosvgs: $(MONOSVGS) icos: $(ICOS) icns: $(ICNS) @@ -52,6 +54,9 @@ $(TRUEPAMS): %.pam: mkicon.py $(SVGS): %.svg: mksvg.py ./mksvg.py $(patsubst %.svg,%_icon,$@) -o $@ +$(MONOSVGS): %.svg: mksvg.py + ./mksvg.py --mode=bw $(patsubst %-mono.svg,%_icon,$@) -o $@ + putty.ico: putty-16.png putty-32.png putty-48.png \ putty-16-mono.png putty-32-mono.png putty-48-mono.png ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ diff --git a/icons/mksvg.py b/icons/mksvg.py index 0ff7d2b7..5c6b71d3 100755 --- a/icons/mksvg.py +++ b/icons/mksvg.py @@ -675,9 +675,12 @@ def box(size, wantback): # Three shades of basically acceptable brown, all achieved by # halftoning between two of the Windows-16 colours. I'm quite # pleased that was feasible at all! - dark = halftone(cr, cK) - med = halftone(cr, cy) - light = halftone(cr, cY) + if not is_bw: + dark = halftone(cr, cK) + med = halftone(cr, cy) + light = halftone(cr, cY) + else: + dark = med = light = halftone(cK, cY) # We define our halftoning parity in such a way that the black # pixels along the RHS of the visible part of the box back # match up with the one-pixel black outline around the @@ -864,33 +867,53 @@ def pageant_icon(size): # Test and output functions. -cK = (0x00, 0x00, 0x00, 0xFF) -cr = (0x80, 0x00, 0x00, 0xFF) -cg = (0x00, 0x80, 0x00, 0xFF) -cy = (0x80, 0x80, 0x00, 0xFF) -cb = (0x00, 0x00, 0x80, 0xFF) -cm = (0x80, 0x00, 0x80, 0xFF) -cc = (0x00, 0x80, 0x80, 0xFF) -cP = (0xC0, 0xC0, 0xC0, 0xFF) -cw = (0x80, 0x80, 0x80, 0xFF) -cR = (0xFF, 0x00, 0x00, 0xFF) -cG = (0x00, 0xFF, 0x00, 0xFF) -cY = (0xFF, 0xFF, 0x00, 0xFF) -cB = (0x00, 0x00, 0xFF, 0xFF) -cM = (0xFF, 0x00, 0xFF, 0xFF) -cC = (0x00, 0xFF, 0xFF, 0xFF) -cW = (0xFF, 0xFF, 0xFF, 0xFF) -cD = (0x00, 0x00, 0x00, 0x80) -cT = (0x00, 0x00, 0x00, 0x00) +def setup_colours(mode): + global cK,cr,cg,cy,cb,cm,cc,cP,cw,cR,cG,cY,cB,cM,cC,cW,cD,cT,is_bw + + is_bw = mode == 'bw' + + cK = (0x00, 0x00, 0x00, 0xFF) + cW = (0xFF, 0xFF, 0xFF, 0xFF) + cT = (0x00, 0x00, 0x00, 0x00) + + if mode == 'colour': + cr = (0x80, 0x00, 0x00, 0xFF) + cg = (0x00, 0x80, 0x00, 0xFF) + cy = (0x80, 0x80, 0x00, 0xFF) + cb = (0x00, 0x00, 0x80, 0xFF) + cm = (0x80, 0x00, 0x80, 0xFF) + cc = (0x00, 0x80, 0x80, 0xFF) + cP = (0xC0, 0xC0, 0xC0, 0xFF) + cw = (0x80, 0x80, 0x80, 0xFF) + cR = (0xFF, 0x00, 0x00, 0xFF) + cG = (0x00, 0xFF, 0x00, 0xFF) + cY = (0xFF, 0xFF, 0x00, 0xFF) + cB = (0x00, 0x00, 0xFF, 0xFF) + cM = (0xFF, 0x00, 0xFF, 0xFF) + cC = (0x00, 0xFF, 0xFF, 0xFF) + cD = (0x00, 0x00, 0x00, 0x80) + elif mode == 'bw': + cr=cg=cb=cm=cc=cP=cw=cR=cG=cB=cM=cC=cD = cK + cY=cy = cW + else: + assert False, f"unexpected mode {mode!r}" def greypix(value): value = max(min(value, 1), 0) + if is_bw: + value = 1 if value > 0.3 else 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) + if is_bw: + return (int(round(0xFF*value)),) * 3 + (0xFF) + else: + 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) + if is_bw: + return (0, 0, 0, 0xFF) + else: + 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))) @@ -928,12 +951,15 @@ def drawicon(func, width, fname): def main(): parser = argparse.ArgumentParser(description='Generate PuTTY SVG icons.') parser.add_argument("icon", help="Which icon to generate.") + parser.add_argument("--mode", choices=('colour', 'bw'), default='colour', + help="Colour mode to generate the icon in.") parser.add_argument("-s", "--size", type=int, default=48, help="Notional pixel size to base the SVG on.") parser.add_argument("-o", "--output", required=True, help="Output file name.") args = parser.parse_args() + setup_colours(args.mode) drawicon(eval(args.icon), args.size, args.output) if __name__ == '__main__': diff --git a/icons/preview.html b/icons/preview.html index 15e02a09..c01eef90 100644 --- a/icons/preview.html +++ b/icons/preview.html @@ -96,7 +96,18 @@ <td><img src="puttyins-48-true.png" /><img src="puttyins-48.png" /></td> </tr> <tr> - <th>SVG</th> + <th>SVG mono</th> + <td><img src="putty-mono.svg" width="128" height="128" /></td> + <td><img src="puttycfg-mono.svg" width="128" height="128" /></td> + <td><img src="pterm-mono.svg" width="128" height="128" /></td> + <td><img src="ptermcfg-mono.svg" width="128" height="128" /></td> + <td><img src="pscp-mono.svg" width="128" height="128" /></td> + <td><img src="pageant-mono.svg" width="128" height="128" /></td> + <td><img src="puttygen-mono.svg" width="128" height="128" /></td> + <td><img src="puttyins-mono.svg" width="128" height="128" /></td> + </tr> + <tr> + <th>SVG colour</th> <td><img src="putty.svg" width="128" height="128" /></td> <td><img src="puttycfg.svg" width="128" height="128" /></td> <td><img src="pterm.svg" width="128" height="128" /></td>