├── .gitignore ├── index.html ├── sizestudy ├── 00-empty.svg ├── 01-beforefont.svg ├── 02-afterfont.svg ├── 03-before-r.svg ├── 04-after-r.svg ├── 05-before-g.svg ├── 06-after-g.svg ├── 07-before-b.svg ├── 08-after-b.svg ├── 09-before-a.svg ├── 10-after-a.svg ├── 11-before-t1.svg ├── 12-after-t1.svg ├── 13-before-t2.svg ├── 14-after-t2.svg ├── 15-before-t3.svg ├── 16-after-t3.svg ├── 17-full.svg ├── run.sh └── sizes.txt └── tools ├── arranger.html ├── maptool.html ├── node ├── package.json ├── palette.json ├── quantize.js └── shrinkwrap.yaml └── shared.js /.gitignore: -------------------------------------------------------------------------------- 1 | # glitch: app user's dotfiles 2 | /.emacs 3 | /.emacs.d 4 | /.lesshst 5 | 6 | # private stuff 7 | /notes.txt 8 | 9 | # glitch: link interpreter info to project root 10 | /package.json 11 | /shrinkwrap.yaml 12 | -------------------------------------------------------------------------------- /sizestudy/00-empty.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wh0/glitter/ddc6a074f43201fe11c762df79026012b40242df/sizestudy/00-empty.svg -------------------------------------------------------------------------------- /sizestudy/01-beforefont.svg: -------------------------------------------------------------------------------- 1 | 2 |

🤓

3 | 4 | 51 | -------------------------------------------------------------------------------- /tools/maptool.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
 4 | 
 5 | 
65 | 
66 | -------------------------------------------------------------------------------- /tools/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "python3 -m http.server $PORT" 4 | }, 5 | "dependencies": { 6 | "canvas": "^2.6.1", 7 | "rgbquant": "^1.1.2" 8 | }, 9 | "engines": { 10 | "node": ">=10" 11 | }, 12 | "glitch": { 13 | "projectType": "generated_static", 14 | "buildDirectory": "." 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tools/node/palette.json: -------------------------------------------------------------------------------- 1 | [[234,198,128],[220,216,128],[203,230,129],[184,242,130],[163,250,131],[140,254,132],[118,254,133],[96,251,134],[75,243,135],[55,232,136],[38,218,137],[23,200,138],[12,181,139],[5,159,140],[1,137,141],[2,115,142],[6,93,143],[14,72,144],[26,52,145],[41,36,146],[59,22,147],[79,12,148],[100,5,149],[123,2,150],[145,3,151],[167,9,152],[187,18,153],[206,31,154],[222,47,155],[235,65,156],[244,86,157],[250,107,158],[251,130,159],[248,152,160],[241,174,161],[231,194,162],[217,211,163],[200,226,164],[180,237,165],[159,245,166],[137,248,167],[114,248,168],[92,243,169],[72,234,170],[53,221,171],[37,205,172],[24,187,173],[15,166,174],[10,144,175],[10,122,176],[14,99,177],[21,78,178],[33,59,179],[48,43,180],[67,29,181],[87,20,182],[109,14,183],[131,13,184],[153,17,185],[175,25,186],[194,36,187],[210,52,188],[223,70,189],[232,91,190],[237,113,191],[237,135,192],[233,157,193],[224,178,194],[211,196,195],[194,212,196],[175,223,197],[153,230,198],[131,233,199],[109,231,200],[87,223,201],[68,212,202],[52,197,203],[39,178,204],[31,157,205],[27,135,206],[29,112,207],[36,91,208],[47,71,209],[63,55,210],[82,43,211],[103,35,212],[125,33,213],[148,36,214],[169,44,215],[187,58,216],[201,75,217],[211,95,218],[216,117,219],[214,140,220],[207,161,221],[195,180,222],[178,195,223],[158,205,224],[136,209,225],[114,207,226],[93,199,227],[75,185,228],[61,167,229],[54,146,230],[53,123,231],[59,102,232],[72,83,233],[89,69,234],[110,61,235],[133,61,236],[154,68,237],[172,82,238],[183,101,239],[187,123,240],[183,145,241],[170,164,242],[151,176,243],[129,179,244],[107,173,245],[91,157,246],[84,136,247],[88,114,248],[103,97,249],[125,92,250],[146,102,251],[154,122,252],[145,142,253],[123,143,254],[128,128,255],[132,112,254],[110,113,253],[101,133,252],[109,153,251],[130,163,250],[152,158,249],[167,141,248],[171,119,247],[164,98,246],[148,82,245],[126,76,244],[104,79,243],[85,91,242],[72,110,241],[68,132,240],[72,154,239],[83,173,238],[101,187,237],[122,194,236],[145,194,235],[166,186,234],[183,172,233],[196,153,232],[202,132,231],[201,109,230],[194,88,229],[180,70,228],[162,56,227],[141,48,226],[119,46,225],[97,50,224],[77,60,223],[60,75,222],[48,94,221],[41,115,220],[39,138,219],[44,160,218],[54,180,217],[68,197,216],[86,211,215],[107,219,214],[130,222,213],[152,220,212],[173,212,211],[192,200,210],[208,184,209],[219,164,208],[226,143,207],[228,120,206],[224,98,205],[216,77,204],[203,58,203],[187,43,202],[168,32,201],[146,24,200],[124,22,199],[102,25,198],[80,32,197],[61,43,196],[44,59,195],[31,77,194],[22,98,193],[18,120,192],[18,142,191],[23,164,190],[32,185,189],[45,203,188],[61,219,187],[80,230,186],[102,238,185],[124,242,184],[146,241,183],[168,235,182],[188,226,181],[207,212,180],[222,196,179],[234,177,178],[241,156,177],[245,133,176],[245,111,175],[240,89,174],[231,68,173],[218,50,172],[202,34,171],[183,21,170],[163,12,169],[141,7,168],[118,7,167],[96,10,166],[75,18,165],[55,29,164],[38,44,163],[24,61,162],[14,81,161],[7,103,160],[4,125,159],[5,148,158],[11,169,157],[20,190,156],[33,208,155],[49,224,154],[68,237,153],[88,246,152],[110,252,151],[132,253,150],[155,250,149],[176,243,148],[196,233,147],[214,219,146],[229,203,145],[241,183,144],[249,162,143],[253,140,142],[254,118,141],[250,96,140],[243,74,139],[232,55,138],[217,37,137],[200,23,136],[180,12,135],[159,4,134],[137,1,133],[115,1,132],[92,5,131],[71,13,130],[52,25,129],[35,39,128]] -------------------------------------------------------------------------------- /tools/node/quantize.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | 5 | const canvas = require('canvas'); 6 | const RgbQuant = require('rgbquant'); 7 | 8 | const palette = require('./palette.json'); 9 | 10 | const [, , src, dst, flag] = process.argv; 11 | 12 | function hasFlag(f) { 13 | return (typeof flag === 'string') && flag.includes(f); 14 | } 15 | 16 | (async () => { 17 | try { 18 | const srcImg = await canvas.loadImage(src); 19 | const c = canvas.createCanvas(srcImg.width, srcImg.height); 20 | const ctx = c.getContext('2d'); 21 | ctx.drawImage(srcImg, 0, 0); 22 | 23 | const dstImageData = canvas.createImageData(srcImg.width, srcImg.height); 24 | const dstData = dstImageData.data; 25 | 26 | const opts = { 27 | palette, 28 | }; 29 | if (hasFlag('d')) { 30 | opts.dithKern = 'FloydSteinberg'; 31 | opts.dithSerp = true; 32 | } 33 | 34 | const q = new RgbQuant(opts); 35 | if (hasFlag('i')) { 36 | console.error('reduce'); 37 | const dstIndices = q.reduce(ctx, 2); 38 | 39 | console.error('convert to index image'); 40 | for (let i = 0; i < dstIndices.length; i++) { 41 | dstData[i * 4] = 255; 42 | dstData[i * 4 + 1] = dstIndices[i]; 43 | dstData[i * 4 + 2] = 0; 44 | dstData[i * 4 + 3] = 255; 45 | } 46 | } else { 47 | console.error('reduce'); 48 | const dstColor = q.reduce(ctx, 1); 49 | 50 | console.error('convert to color image'); 51 | dstData.set(dstColor); 52 | } 53 | 54 | console.error('encode'); 55 | ctx.putImageData(dstImageData, 0, 0); 56 | const dstBuffer = c.toBuffer('image/png'); 57 | 58 | console.error('writeFile'); 59 | await fs.promises.writeFile(dst, dstBuffer); 60 | } catch (e) { 61 | console.error(e); 62 | process.exit(1); 63 | } 64 | })(); 65 | -------------------------------------------------------------------------------- /tools/node/shrinkwrap.yaml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | canvas: 2.7.0 3 | rgbquant: 1.1.2 4 | packages: 5 | /abbrev/1.1.1: 6 | dev: false 7 | resolution: 8 | integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== 9 | /ansi-regex/2.1.1: 10 | dev: false 11 | engines: 12 | node: '>=0.10.0' 13 | resolution: 14 | integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 15 | /ansi-regex/3.0.0: 16 | dev: false 17 | engines: 18 | node: '>=4' 19 | resolution: 20 | integrity: sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 21 | /aproba/1.2.0: 22 | dev: false 23 | resolution: 24 | integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== 25 | /are-we-there-yet/1.1.5: 26 | dependencies: 27 | delegates: 1.0.0 28 | readable-stream: 2.3.7 29 | dev: false 30 | resolution: 31 | integrity: sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== 32 | /balanced-match/1.0.0: 33 | dev: false 34 | resolution: 35 | integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 36 | /brace-expansion/1.1.11: 37 | dependencies: 38 | balanced-match: 1.0.0 39 | concat-map: 0.0.1 40 | dev: false 41 | resolution: 42 | integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 43 | /canvas/2.7.0: 44 | dependencies: 45 | nan: 2.14.2 46 | node-pre-gyp: 0.15.0 47 | simple-get: 3.1.0 48 | dev: false 49 | engines: 50 | node: '>=6' 51 | requiresBuild: true 52 | resolution: 53 | integrity: sha512-pzCxtkHb+5su5MQjTtepMDlIOtaXo277x0C0u3nMOxtkhTyQ+h2yNKhlROAaDllWgRyePAUitC08sXw26Eb6aw== 54 | /chownr/1.1.4: 55 | dev: false 56 | resolution: 57 | integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== 58 | /code-point-at/1.1.0: 59 | dev: false 60 | engines: 61 | node: '>=0.10.0' 62 | resolution: 63 | integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 64 | /concat-map/0.0.1: 65 | dev: false 66 | resolution: 67 | integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 68 | /console-control-strings/1.1.0: 69 | dev: false 70 | resolution: 71 | integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= 72 | /core-util-is/1.0.2: 73 | dev: false 74 | resolution: 75 | integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 76 | /debug/3.2.7: 77 | dependencies: 78 | ms: 2.1.3 79 | dev: false 80 | resolution: 81 | integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 82 | /decompress-response/4.2.1: 83 | dependencies: 84 | mimic-response: 2.1.0 85 | dev: false 86 | engines: 87 | node: '>=8' 88 | resolution: 89 | integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== 90 | /deep-extend/0.6.0: 91 | dev: false 92 | engines: 93 | node: '>=4.0.0' 94 | resolution: 95 | integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== 96 | /delegates/1.0.0: 97 | dev: false 98 | resolution: 99 | integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= 100 | /detect-libc/1.0.3: 101 | dev: false 102 | engines: 103 | node: '>=0.10' 104 | hasBin: true 105 | resolution: 106 | integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= 107 | /fs-minipass/1.2.7: 108 | dependencies: 109 | minipass: 2.9.0 110 | dev: false 111 | resolution: 112 | integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== 113 | /fs.realpath/1.0.0: 114 | dev: false 115 | resolution: 116 | integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 117 | /gauge/2.7.4: 118 | dependencies: 119 | aproba: 1.2.0 120 | console-control-strings: 1.1.0 121 | has-unicode: 2.0.1 122 | object-assign: 4.1.1 123 | signal-exit: 3.0.3 124 | string-width: 1.0.2 125 | strip-ansi: 3.0.1 126 | wide-align: 1.1.3 127 | dev: false 128 | resolution: 129 | integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= 130 | /glob/7.1.6: 131 | dependencies: 132 | fs.realpath: 1.0.0 133 | inflight: 1.0.6 134 | inherits: 2.0.4 135 | minimatch: 3.0.4 136 | once: 1.4.0 137 | path-is-absolute: 1.0.1 138 | dev: false 139 | resolution: 140 | integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 141 | /has-unicode/2.0.1: 142 | dev: false 143 | resolution: 144 | integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= 145 | /iconv-lite/0.4.24: 146 | dependencies: 147 | safer-buffer: 2.1.2 148 | dev: false 149 | engines: 150 | node: '>=0.10.0' 151 | resolution: 152 | integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 153 | /ignore-walk/3.0.3: 154 | dependencies: 155 | minimatch: 3.0.4 156 | dev: false 157 | resolution: 158 | integrity: sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== 159 | /inflight/1.0.6: 160 | dependencies: 161 | once: 1.4.0 162 | wrappy: 1.0.2 163 | dev: false 164 | resolution: 165 | integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 166 | /inherits/2.0.4: 167 | dev: false 168 | resolution: 169 | integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 170 | /ini/1.3.8: 171 | dev: false 172 | resolution: 173 | integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== 174 | /is-fullwidth-code-point/1.0.0: 175 | dependencies: 176 | number-is-nan: 1.0.1 177 | dev: false 178 | engines: 179 | node: '>=0.10.0' 180 | resolution: 181 | integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 182 | /is-fullwidth-code-point/2.0.0: 183 | dev: false 184 | engines: 185 | node: '>=4' 186 | resolution: 187 | integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 188 | /isarray/1.0.0: 189 | dev: false 190 | resolution: 191 | integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 192 | /mimic-response/2.1.0: 193 | dev: false 194 | engines: 195 | node: '>=8' 196 | resolution: 197 | integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== 198 | /minimatch/3.0.4: 199 | dependencies: 200 | brace-expansion: 1.1.11 201 | dev: false 202 | resolution: 203 | integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 204 | /minimist/1.2.5: 205 | dev: false 206 | resolution: 207 | integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 208 | /minipass/2.9.0: 209 | dependencies: 210 | safe-buffer: 5.2.1 211 | yallist: 3.1.1 212 | dev: false 213 | resolution: 214 | integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== 215 | /minizlib/1.3.3: 216 | dependencies: 217 | minipass: 2.9.0 218 | dev: false 219 | resolution: 220 | integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== 221 | /mkdirp/0.5.5: 222 | dependencies: 223 | minimist: 1.2.5 224 | dev: false 225 | hasBin: true 226 | resolution: 227 | integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 228 | /ms/2.1.3: 229 | dev: false 230 | resolution: 231 | integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 232 | /nan/2.14.2: 233 | dev: false 234 | resolution: 235 | integrity: sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== 236 | /needle/2.6.0: 237 | dependencies: 238 | debug: 3.2.7 239 | iconv-lite: 0.4.24 240 | sax: 1.2.4 241 | dev: false 242 | engines: 243 | node: '>= 4.4.x' 244 | hasBin: true 245 | resolution: 246 | integrity: sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg== 247 | /node-pre-gyp/0.15.0: 248 | dependencies: 249 | detect-libc: 1.0.3 250 | mkdirp: 0.5.5 251 | needle: 2.6.0 252 | nopt: 4.0.3 253 | npm-packlist: 1.4.8 254 | npmlog: 4.1.2 255 | rc: 1.2.8 256 | rimraf: 2.7.1 257 | semver: 5.7.1 258 | tar: 4.4.13 259 | deprecated: 'Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future' 260 | dev: false 261 | hasBin: true 262 | resolution: 263 | integrity: sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA== 264 | /nopt/4.0.3: 265 | dependencies: 266 | abbrev: 1.1.1 267 | osenv: 0.1.5 268 | dev: false 269 | hasBin: true 270 | resolution: 271 | integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== 272 | /npm-bundled/1.1.1: 273 | dependencies: 274 | npm-normalize-package-bin: 1.0.1 275 | dev: false 276 | resolution: 277 | integrity: sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== 278 | /npm-normalize-package-bin/1.0.1: 279 | dev: false 280 | resolution: 281 | integrity: sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== 282 | /npm-packlist/1.4.8: 283 | dependencies: 284 | ignore-walk: 3.0.3 285 | npm-bundled: 1.1.1 286 | npm-normalize-package-bin: 1.0.1 287 | dev: false 288 | resolution: 289 | integrity: sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== 290 | /npmlog/4.1.2: 291 | dependencies: 292 | are-we-there-yet: 1.1.5 293 | console-control-strings: 1.1.0 294 | gauge: 2.7.4 295 | set-blocking: 2.0.0 296 | dev: false 297 | resolution: 298 | integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== 299 | /number-is-nan/1.0.1: 300 | dev: false 301 | engines: 302 | node: '>=0.10.0' 303 | resolution: 304 | integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 305 | /object-assign/4.1.1: 306 | dev: false 307 | engines: 308 | node: '>=0.10.0' 309 | resolution: 310 | integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 311 | /once/1.4.0: 312 | dependencies: 313 | wrappy: 1.0.2 314 | dev: false 315 | resolution: 316 | integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 317 | /os-homedir/1.0.2: 318 | dev: false 319 | engines: 320 | node: '>=0.10.0' 321 | resolution: 322 | integrity: sha1-/7xJiDNuDoM94MFox+8VISGqf7M= 323 | /os-tmpdir/1.0.2: 324 | dev: false 325 | engines: 326 | node: '>=0.10.0' 327 | resolution: 328 | integrity: sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 329 | /osenv/0.1.5: 330 | dependencies: 331 | os-homedir: 1.0.2 332 | os-tmpdir: 1.0.2 333 | dev: false 334 | resolution: 335 | integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== 336 | /path-is-absolute/1.0.1: 337 | dev: false 338 | engines: 339 | node: '>=0.10.0' 340 | resolution: 341 | integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 342 | /process-nextick-args/2.0.1: 343 | dev: false 344 | resolution: 345 | integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 346 | /rc/1.2.8: 347 | dependencies: 348 | deep-extend: 0.6.0 349 | ini: 1.3.8 350 | minimist: 1.2.5 351 | strip-json-comments: 2.0.1 352 | dev: false 353 | hasBin: true 354 | resolution: 355 | integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== 356 | /readable-stream/2.3.7: 357 | dependencies: 358 | core-util-is: 1.0.2 359 | inherits: 2.0.4 360 | isarray: 1.0.0 361 | process-nextick-args: 2.0.1 362 | safe-buffer: 5.1.2 363 | string_decoder: 1.1.1 364 | util-deprecate: 1.0.2 365 | dev: false 366 | resolution: 367 | integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 368 | /rgbquant/1.1.2: 369 | dev: false 370 | resolution: 371 | integrity: sha1-2V6Imo/LHmwaT6LMyL46QaL80YU= 372 | /rimraf/2.7.1: 373 | dependencies: 374 | glob: 7.1.6 375 | dev: false 376 | hasBin: true 377 | resolution: 378 | integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 379 | /safe-buffer/5.1.2: 380 | dev: false 381 | resolution: 382 | integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 383 | /safe-buffer/5.2.1: 384 | dev: false 385 | resolution: 386 | integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 387 | /safer-buffer/2.1.2: 388 | dev: false 389 | resolution: 390 | integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 391 | /sax/1.2.4: 392 | dev: false 393 | resolution: 394 | integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== 395 | /semver/5.7.1: 396 | dev: false 397 | hasBin: true 398 | resolution: 399 | integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 400 | /set-blocking/2.0.0: 401 | dev: false 402 | resolution: 403 | integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 404 | /signal-exit/3.0.3: 405 | dev: false 406 | resolution: 407 | integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 408 | /simple-concat/1.0.1: 409 | dev: false 410 | resolution: 411 | integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== 412 | /simple-get/3.1.0: 413 | dependencies: 414 | decompress-response: 4.2.1 415 | once: 1.4.0 416 | simple-concat: 1.0.1 417 | dev: false 418 | resolution: 419 | integrity: sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== 420 | /string-width/1.0.2: 421 | dependencies: 422 | code-point-at: 1.1.0 423 | is-fullwidth-code-point: 1.0.0 424 | strip-ansi: 3.0.1 425 | dev: false 426 | engines: 427 | node: '>=0.10.0' 428 | resolution: 429 | integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 430 | /string-width/2.1.1: 431 | dependencies: 432 | is-fullwidth-code-point: 2.0.0 433 | strip-ansi: 4.0.0 434 | dev: false 435 | engines: 436 | node: '>=4' 437 | resolution: 438 | integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 439 | /string_decoder/1.1.1: 440 | dependencies: 441 | safe-buffer: 5.1.2 442 | dev: false 443 | resolution: 444 | integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 445 | /strip-ansi/3.0.1: 446 | dependencies: 447 | ansi-regex: 2.1.1 448 | dev: false 449 | engines: 450 | node: '>=0.10.0' 451 | resolution: 452 | integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 453 | /strip-ansi/4.0.0: 454 | dependencies: 455 | ansi-regex: 3.0.0 456 | dev: false 457 | engines: 458 | node: '>=4' 459 | resolution: 460 | integrity: sha1-qEeQIusaw2iocTibY1JixQXuNo8= 461 | /strip-json-comments/2.0.1: 462 | dev: false 463 | engines: 464 | node: '>=0.10.0' 465 | resolution: 466 | integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo= 467 | /tar/4.4.13: 468 | dependencies: 469 | chownr: 1.1.4 470 | fs-minipass: 1.2.7 471 | minipass: 2.9.0 472 | minizlib: 1.3.3 473 | mkdirp: 0.5.5 474 | safe-buffer: 5.2.1 475 | yallist: 3.1.1 476 | dev: false 477 | engines: 478 | node: '>=4.5' 479 | resolution: 480 | integrity: sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== 481 | /util-deprecate/1.0.2: 482 | dev: false 483 | resolution: 484 | integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 485 | /wide-align/1.1.3: 486 | dependencies: 487 | string-width: 2.1.1 488 | dev: false 489 | resolution: 490 | integrity: sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== 491 | /wrappy/1.0.2: 492 | dev: false 493 | resolution: 494 | integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 495 | /yallist/3.1.1: 496 | dev: false 497 | resolution: 498 | integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 499 | registry: 'https://registry.npmjs.org/' 500 | shrinkwrapMinorVersion: 9 501 | shrinkwrapVersion: 3 502 | specifiers: 503 | canvas: ^2.6.1 504 | rgbquant: ^1.1.2 505 | -------------------------------------------------------------------------------- /tools/shared.js: -------------------------------------------------------------------------------- 1 | function fromSpherical([phi, theta]) { 2 | const z = Math.cos(phi); 3 | const sinPhi = Math.sin(phi); 4 | const x = sinPhi * Math.sin(theta); 5 | const y = sinPhi * Math.cos(theta); 6 | return [x, y, z]; 7 | } 8 | function chooseNormal(j, J) { 9 | const s = j / J * 2 - 1; 10 | const side = s < 0 ? -1 : 1; 11 | const revs = Math.sqrt(J / 8); 12 | const thetaStep = revs * 4; 13 | const phi = Math.acos(1 - Math.abs(s)) * side; 14 | const theta = phi * thetaStep * side; 15 | return fromSpherical([phi, theta]); 16 | } 17 | function dot([ax, ay, az], [bx, by, bz]) { 18 | return ax * bx + ay * by + az * bz; 19 | } 20 | function scale(s, [x, y, z]) { 21 | return [s * x, s * y, s * z]; 22 | } 23 | function add3([ax, ay, az], [bx, by, bz]) { 24 | return [ax + bx, ay + by, az + bz]; 25 | } 26 | function reflect(n, l, nl) { 27 | return add3(l, scale(2, add3(scale(nl, n), scale(-1, l)))); 28 | } 29 | function light(v, n, l, iDiffuse, iSpecular, kSpecular) { 30 | const nl = dot(n, l); 31 | const r = reflect(n, l, nl); 32 | const vr = dot(v, r); 33 | const diffuse = Math.max(nl, 0) * iDiffuse; 34 | const specular = Math.pow(Math.max(vr, 0), kSpecular) * iSpecular; 35 | return [diffuse, specular]; 36 | } 37 | function add2([a0, a1], [b0, b1]) { 38 | return [a0 + b0, a1 + b1]; 39 | } 40 | --------------------------------------------------------------------------------