diff options
author | Rasmus Andersson <rasmus@notion.se> | 2023-09-27 03:10:58 +0300 |
---|---|---|
committer | Rasmus Andersson <rasmus@notion.se> | 2023-09-27 03:10:58 +0300 |
commit | 2f9a256e6ec42dd10c71db3b865bfe83811ecf3a (patch) | |
tree | c5a7c4c9e056b51be04d8dffa47be1c703deb9a9 /docs/glyphs/glyphs.js | |
parent | c2452dee3a25f6b4710348bc7a5b585c31037bf3 (diff) | |
download | inter-2f9a256e6ec42dd10c71db3b865bfe83811ecf3a.tar.xz |
new v4 website
Diffstat (limited to 'docs/glyphs/glyphs.js')
-rw-r--r-- | docs/glyphs/glyphs.js | 807 |
1 files changed, 0 insertions, 807 deletions
diff --git a/docs/glyphs/glyphs.js b/docs/glyphs/glyphs.js deleted file mode 100644 index c0a9ae20b..000000000 --- a/docs/glyphs/glyphs.js +++ /dev/null @@ -1,807 +0,0 @@ -// constants -var kSVGScale = 0.1 // how bmuch metrics are scaled in the SVGs -var kGlyphSize = 346 // at kSVGScale. In sync with CSS and SVGs -var kUPM = 2816 - - -function pxround(n) { - return Math.round(n * 2) / 2 -} - -// forEachElement(selector, fun) -// forEachElement(parent, selector, fun) -function eachElement(parent, selector, fun) { - if (typeof selector == 'function') { - fun = selector - selector = parent - parent = document - } - Array.prototype.forEach.call(parent.querySelectorAll(selector), fun) -} - - -if (!isMac) { - eachElement('kbd', function(e) { - if (e.innerText == '\u2318') { - e.innerText = 'Ctrl' - } - }) -} - -function httpget(url, cb) { - var req = new XMLHttpRequest(); - req.addEventListener("load", function() { - cb(this.responseText, this) - }) - req.open("GET", url) - req.send() -} - -function fetchGlyphInfo(cb) { - httpget("../lab/glyphinfo.json", function(res) { - cb(JSON.parse(res).glyphs) - }) -} - -function fetchMetrics(cb) { - httpget("metrics.json", function(res) { - cb(JSON.parse(res)) - }) -} - -var glyphInfo = null -var glyphMetrics = null - -function initMetrics(data) { - // metrics.json uses a compact format with numerical glyph indentifiers - // in order to minimize file size. - // We expand the glyph IDs to glyph names here. - var nameIds = data.nameids - // console.log(data) - - var metrics = {} - var metrics0 = data.metrics - Object.keys(metrics0).forEach(function (id) { - var name = nameIds[id] - var v = metrics0[id] - // v : [width, advance, left, right] - metrics[name] = { - width: v[0], - advance: v[1], - left: v[2], - right: v[3] - } - }) - - var kerningLeft = {} // { glyphName: {rightGlyphName: kerningValue, ...}, ... } - var kerningRight = {} - data.kerning.forEach(function (t) { - // each entry looks like this: - // [leftGlyphId, rightGlyphId, kerningValue] - var leftName = nameIds[t[0]] - if (!leftName) { - console.error('nameIds missing', t[0]) - } - var rightName = nameIds[t[1]] - if (!rightName) { - console.error('nameIds missing', t[1]) - } - var kerningValue = t[2] - - var lm = kerningLeft[leftName] - if (!lm) { - kerningLeft[leftName] = lm = {} - } - lm[rightName] = kerningValue - - var rm = kerningRight[rightName] - if (!rm) { - kerningRight[rightName] = rm = {} - } - rm[leftName] = kerningValue - }) - - glyphMetrics = { - metrics: metrics, - kerningLeft: kerningLeft, - kerningRight: kerningRight, - } - // console.log('glyphMetrics', glyphMetrics) -} - -function fetchAll(cb) { - var i = 0 - var res = {} - var decr = function(){ - if (--i == 0) { - cb(res) - } - } - i++ - fetchGlyphInfo(function(r){ glyphInfo = r; decr() }) - i++ - fetchMetrics(function(r){ - initMetrics(r) - decr() - }) -} - -fetchAll(render) - - -var styleSheet = document.styleSheets[document.styleSheets.length-1] -var glyphRule, lineRule, zeroWidthAdvRule -var currentScale = 1 -var defaultSingleScale = 1 -var currentSingleScale = 1 -var defaultGridScale = 0.4 -var currentGridScale = defaultGridScale -var glyphs = document.getElementById('glyphs') - -function updateLayoutAfterChanges() { - var height = parseInt(window.getComputedStyle(glyphs).height) - var margin = height - (height * currentScale) - // console.log('scale:', currentScale, 'height:', height, 'margin:', margin) - if (currentScale > 1) { - glyphs.style.marginBottom = null - } else { - glyphs.style.marginBottom = -margin + 'px' - } -} - - - - -function encodeQueryString(q) { - return Object.keys(q).map(function(k) { - if (k) { - var v = q[k] - return encodeURIComponent(k) + (v ? '=' + encodeURIComponent(v) : '') - } - }).filter(function(s) { return !!s }).join('&') -} - -function parseQueryString(qs) { - var q = {} - qs.replace(/^\?/,'').split('&').forEach(function(c) { - var kv = c.split('=') - var k = decodeURIComponent(kv[0]) - if (k) { - q[k] = kv[1] ? decodeURIComponent(kv[1]) : null - } - }) - return q -} - - -var queryString = parseQueryString(location.search) -var glyphNameEl = null -var baseTitle = document.title -var flippedLocationHash = false - -var singleInfo = document.querySelector('#single-info') -singleInfo.parentElement.removeChild(singleInfo) -singleInfo.style.display = 'block' - -function updateLocation() { - queryString = parseQueryString(location.search) - // console.log("updateLocation. queryString=", queryString) - - var h1 = document.querySelector('h1') - if (queryString.g) { - if (!glyphNameEl) { - glyphNameEl = document.createElement('a') - glyphNameEl.href = '?g=' + encodeURIComponent(queryString.g) - wrapIntLink(glyphNameEl) - glyphNameEl.className = 'glyph-name' - } - document.title = queryString.g + ' – ' + baseTitle - glyphNameEl.innerText = queryString.g - h1.appendChild(glyphNameEl) - document.body.classList.add('single') - render() - } else { - document.title = baseTitle - if (glyphNameEl) { - try { h1.removeChild(glyphNameEl) } catch(_) {} - } - document.body.classList.remove('single') - } - // render() -} - -window.onpopstate = function(ev) { - updateLocation() -} - -function navto(url) { - if (location.href != url) { - history.pushState({}, "Glyphs", url) - updateLocation() - } - window.scrollTo(0,0) -} - -function wrapIntLink(a) { - a.addEventListener('click', function(ev) { - if (!ev.metaKey && !ev.ctrlKey && !ev.shiftKey) { - ev.preventDefault() - navto(a.href) - } - }) -} - -wrapIntLink(document.querySelector('h1 > a')) - - -// keep refs to svgs so we don't have to refcount while using -var svgRepository = null -function getGlyphSVG(name) { - if (!svgRepository) { - svgRepository = {} - let svgs = document.getElementById('svgs') - for (let i = 0; i < svgs.children.length; ++i) { - let svg = svgs.children[i] - let name = svg.id.substr(4) // strip "svg-" prefix - svgRepository[name] = svg - } - } - return svgRepository[name] -} - - -// Maps glyphname to glyphInfo. Only links to first found entry for a flyph. -var glyphInfoMap = {} - - -function render() { - let glyphname = queryString.g - - if (!glyphInfo || !glyphname) { - return - } - - var rootEl = document.getElementById('glyphs') - rootEl.style.display = 'none' - rootEl.innerText = '' - - // glyphinfo.json: - // { "glyphs": [ - // [name :string, isEmpty: 1|0, unicode? :string|null, - // unicodeName? :string, color? :string|null], - // ["A", 0, 65, "LATIN CAPITAL LETTER A", "#dbeaf7"], - // ... - // ]} - // - // Note: Glyph names might appear multiple times (always adjacent) when a glyph is - // represented by multiple Unicode code points. For example: - // - // ["Delta", 0, "U+0916", "GREEK CAPITAL LETTER DELTA"], - // ["Delta", 0, "U+8710", "INCREMENT"], - // - - let g; - - for (let i = 0; i < glyphInfo.length; i++) { - g = glyphInfo[i] - if (glyphname == g[0]) { - let glyph = renderGlyphGraphicG(g) - if (glyph) { - rootEl.appendChild(glyph.element) - renderSingleInfo(glyph) - rootEl.appendChild(singleInfo) - } - break - } - } - - renderStyleSpectrum(g) - - rootEl.style.display = null - updateLayoutAfterChanges() -} - - -const stringFromCodePoint = String.fromCodePoint || function(c) { - return String.fromCharCode(c) -} - - -function glyphIsXL(g) { - let m - return glyphMetrics && (m = glyphMetrics.metrics[g[0]]) && m.advance > 3200 - // console.log("glyphMetrics.metrics", glyphMetrics.metrics[g[0]]) - // return g[0].indexOf(".circled") != -1 -} - - -function renderStyleSpectrum(g) { - // console.log("renderStyleSpectrum", g) - let list = document.querySelector("#style-spectrum") - list.innerText = "" - - let s = stringFromCodePoint(parseInt(g[2],16)) - list.classList.toggle("xl", glyphIsXL(g)) - - for (let slant = 0; slant <= 10; slant += 2) { - for (let weight = 100; weight <= 900; weight += 100) { - let el = document.createElement("div") - el.innerText = s - el.title = `wght ${weight}, slnt -${slant}°` - el.style.fontWeight = weight - if (slant > 0) { - el.style.fontStyle = "italic" - } - el.style.webkitFontVariationSettings = el.style.fontVariationSettings = - `'wght' ${weight}, 'slnt' -${slant}` - list.appendChild(el) - } - list.appendChild(document.createElement("br")) - } -} - - -function renderGlyphGraphic(glyphName) { - var g = glyphInfoMap[glyphName] - return g ? renderGlyphGraphicG(g) : null -} - - -function renderGlyphGraphicG(g /*, lastGlyphName, lastGlyphEl, singleGlyph*/) { - // let [name, isEmpty, uc, ucName, color] = g - let name = g[0], /*isEmpty = g[1],*/ uc = g[2], ucName = g[3], color = g[4] - var names, glyph - var svg = getGlyphSVG(name) - - if (!svg) { - // ignore - return null - } - - var metrics = glyphMetrics.metrics[name] - if (!metrics) { - console.error('missing metrics for', name) - } - - var info = { - name: name, - unicode: uc, - unicodeName: ucName, - color: color, - - // These are all in 1:1 UPM (not scaled) - advance: metrics.advance, - left: metrics.left, - right: metrics.right, - width: metrics.width, - - element: null, - } - - // if (name == lastGlyphName) { - // // additional Unicode code point for same glyph - // glyph = lastGlyphEl - // names = glyph.querySelector('.names') - // names.innerText += ',' - // if (info.unicode) { - // var ucid = ' U+' + info.unicode - // names.innerText += ' U+' + info.unicode - // if (!queryString.g) { - // glyph.title += ucid - // } - // } - // if (info.unicodeName) { - // names.innerText += ' ' + info.unicodeName - // if (!queryString.g) { - // glyph.title += ' (' + info.unicodeName + ')' - // } - // } - - // if (queryString.g) { - // if (singleGlyph) { - // if (!singleGlyph.alternates) { - // singleGlyph.alternates = [] - // } - // singleGlyph.alternates.push(info) - // } else { - // throw new Error('alternate glyph UC, but appears first in glyphinfo data') - // } - // } - - // return - // } - - // console.log('svg for', name, svg.width.baseVal.value, '->', svg, '\n', info) - - glyph = document.createElement('a') - glyph.className = 'glyph' - glyph.href = '?g=' + encodeURIComponent(name) - wrapIntLink(glyph) - - info.element = glyph - - if (!queryString.g) { - glyph.title = name - } - - var line = document.createElement('div') - line.className = 'line baseline' - line.title = "Baseline" - glyph.appendChild(line) - - line = document.createElement('div') - line.className = 'line x-height' - line.title = "x-height" - glyph.appendChild(line) - - line = document.createElement('div') - line.className = 'line cap-height' - line.title = "Cap height" - glyph.appendChild(line) - - names = document.createElement('div') - names.className = 'names' - names.innerText = name - if (info.unicode) { - var ucid = ' U+' + info.unicode - names.innerText += ' U+' + info.unicode - if (!queryString.g) { - glyph.title += ucid - } - } - if (info.unicodeName) { - names.innerText += ' ' + info.unicodeName - if (!queryString.g) { - glyph.title += ' (' + info.unicodeName + ')' - } - } - glyph.appendChild(names) - - var scaledAdvance = info.advance * kSVGScale - - if (scaledAdvance > kGlyphSize) { - glyph.style.width = scaledAdvance.toFixed(2) + 'px' - } - - var adv = document.createElement('div') - adv.className = 'advance' - glyph.appendChild(adv) - - adv.appendChild(svg) - svg.style.left = (info.left * kSVGScale).toFixed(2) + 'px' - - if (info.advance <= 0) { - glyph.className += ' zero-width' - } else { - adv.style.width = scaledAdvance.toFixed(2) + 'px' - } - - return info -} - - -function renderSingleInfo(g) { - var e = singleInfo - e.querySelector('.name').innerText = g.name - - function setv(el, name, textValue) { - el.querySelector('.' + name).innerText = textValue - } - - var unicode = e.querySelector('.unicode') - - function configureUnicodeView(el, g) { - var a = el.querySelector('a') - if (g.unicode) { - a.href = "https://codepoints.net/U+" + g.unicode - } else { - a.href = '' - } - setv(el, 'unicodeCodePoint', g.unicode ? 'U+' + g.unicode : '–') - setv(el, 'unicodeName', g.unicodeName || '') - } - - // remove any previous alternate unicode list items - var rmli = unicode - while ((rmli = rmli.nextSibling)) { - if (rmli.nodeType == Node.ELEMENT_NODE) { - if (!rmli.parentElement || !rmli.classList.contains('unicode')) { - break - } - rmli.parentElement.removeChild(rmli) - } - } - - configureUnicodeView(unicode, g) - - if (g.alternates) { - var refnode = unicode.nextSibling - g.alternates.forEach(function(g) { - var li = unicode.cloneNode(true) - configureUnicodeView(li, g) - if (refnode) { - unicode.parentElement.insertBefore(li, unicode.nextSibling) - } else { - unicode.parentElement.appendChild(li) - } - }) - } - - e.querySelector('.advanceWidth').innerText = g.advance - e.querySelector('.marginLeft').innerText = g.left - e.querySelector('.marginRight').innerText = g.right - - var colorMark = e.querySelector('.colorMark') - if (g.color) { - colorMark.title = g.color.toUpperCase() - colorMark.style.background = g.color - colorMark.classList.remove('none') - } else { - colorMark.title = '(None)' - colorMark.style.background = null - colorMark.classList.add('none') - } - - var svg = getGlyphSVG(g.name) - var svgFile = e.querySelector('.svgFile') - svgFile.download = g.name + '.svg' - svgFile.href = getSvgDataURI(svg) - - renderSingleKerning(g) -} - - -var cachedSVGDataURIs = {} - -function getSvgDataURI(svg, fill) { - if (!fill) { - fill = '' - } - var cached = cachedSVGDataURIs[svg.id + '-' + fill] - if (!cached) { - var src = svg.outerHTML.replace(/[\r\n]+/g, '') - if (fill) { - src = src.replace(/<path /g, '<path fill="' + fill + '" ') - } - cached = 'data:image/svg+xml,' + src - cachedSVGDataURIs[svg.id + '-' + fill] = cached - } - return cached -} - - - -function selectKerningPair(id, directly) { - // deselect existing - eachElement('.kernpair.selected', function(kernpair) { - eachElement(kernpair, '.g', function (glyph) { - var svgURI = getSvgDataURI(getGlyphSVG(glyph.dataset.name)) - glyph.style.backgroundImage = "url('" + svgURI + "')" - }) - kernpair.classList.remove('selected') - }) - - var el = document.getElementById(id) - - if (!el) { - history.replaceState({}, '', location.search) - return - } - - el.classList.add('selected') - eachElement(el, '.g', function (glyph) { - var svgURI = getSvgDataURI(getGlyphSVG(glyph.dataset.name), 'white') - glyph.style.backgroundImage = "url('" + svgURI + "')" - }) - - if (!directly) { - el.scrollIntoViewIfNeeded() - } - - history.replaceState({}, '', location.search + '#' + id) -} - - -// return true if some kerning was rendered -function renderSingleKerning(g) { - var kerningList = document.getElementById('kerning-list') - kerningList.style.display = 'none' - kerningList.innerText = '' - var thisSvg = getGlyphSVG(g.name) - var thisSvgURI = getSvgDataURI(thisSvg) - - if (!thisSvg) { - kerningList.style.display = null - return false - } - - var kerningAsLeft = glyphMetrics.kerningLeft[g.name] || {} - var kerningAsRight = glyphMetrics.kerningRight[g.name] || {} - - var kerningAsLeftKeys = Object.keys(kerningAsLeft) - var kerningAsRightKeys = Object.keys(kerningAsRight) - - if (kerningAsLeftKeys.length == 0 && kerningAsRightKeys.length == 0) { - var p = document.createElement('p') - p.className = 'empty' - p.innerText = 'No kerning' - kerningList.appendChild(p) - kerningList.style.display = null - return false - } - - var lilGlyphSize = 128 - var lilScale = lilGlyphSize / kGlyphSize - - function mkpairGlyph(glyphName, side, kerningValue, svgURI) { - var metrics = glyphMetrics.metrics[glyphName] - var svgWidth = pxround(metrics.width * kSVGScale * lilScale) - var el = document.createElement('div') - - var leftMargin = metrics.left - var rightMargin = metrics.right - if (side == 'left') { - rightMargin += kerningValue - } else { - leftMargin += kerningValue - } - leftMargin = leftMargin * kSVGScale * lilScale - rightMargin = rightMargin * kSVGScale * lilScale - - el.dataset.name = glyphName - el.className = 'g ' + side - el.style.backgroundImage = "url('" + svgURI + "')" - el.style.backgroundSize = svgWidth + 'px ' + lilGlyphSize + 'px' - el.style.width = svgWidth + 'px' - el.style.height = lilGlyphSize + 'px' - el.style.marginLeft = pxround(leftMargin) + 'px' - el.style.marginRight = pxround(rightMargin) + 'px' - return el - } - - function mkpairs(kerningInfo, selfName, self, side) { - var asLeftSide = side == 'left' - var idPrefix = asLeftSide ? 'kernl-' : 'kernr-' - var keys = Object.keys(kerningInfo) - var otherSide = asLeftSide ? 'right' : 'left' - - keys.forEach(function(glyphName) { - var kerningValue = kerningInfo[glyphName] - var otherSvg = getGlyphSVG(glyphName) - - var pair = document.createElement('a') - pair.className = 'kernpair ' + side - pair.title = ( - asLeftSide ? selfName + '/' + glyphName + ' ' + kerningValue : - glyphName + '/' + selfName + ' ' + kerningValue - ) - pair.id = idPrefix + glyphName - pair.href = '#' + pair.id - pair.onclick = function(ev) { - selectKerningPair(pair.id) - ev.preventDefault() - ev.stopPropagation() - } - - var otherEl = mkpairGlyph(glyphName, otherSide, kerningValue, getSvgDataURI(otherSvg)) - - if (asLeftSide) { - if (self.parentNode) { - pair.appendChild(self.cloneNode(true)) - } else { - pair.appendChild(self) - } - pair.appendChild(otherEl) - } else { - pair.appendChild(otherEl) - if (self.parentNode) { - pair.appendChild(self.cloneNode(true)) - } else { - pair.appendChild(self) - } - } - - var kern = document.createElement('div') - kern.className = 'kern ' + (kerningValue < 0 ? 'neg' : 'pos') - - var absKernVal = Math.abs(kerningValue) - var kernWidth = Math.max(1, pxround(absKernVal * kSVGScale * lilScale)) - kern.style.width = kernWidth + 'px' - - var leftMetrics = glyphMetrics.metrics[asLeftSide ? selfName : glyphName] - var leftAdvance = leftMetrics.advance - kern.style.left = pxround((leftAdvance - absKernVal) * kSVGScale * lilScale) + 'px' - pair.appendChild(kern) - - var label = document.createElement('div') - label.className = 'label' - label.innerText = kerningValue - kern.appendChild(label) - - if (glyphName != selfName) { - var link = document.createElement('div') - link.className = 'link' - var linkA = document.createElement('a') - linkA.href = '?g=' + encodeURIComponent(glyphName) - linkA.title = 'View ' + glyphName - linkA.innerText = '\u2197' - linkA.tabIndex = -1 - wrapIntLink(linkA) - link.appendChild(linkA) - - var kLinkAWidth = 16 // sync with CSS .kernpair .link a - - if (asLeftSide) { - var rightMetrics = glyphMetrics.metrics[asLeftSide ? glyphName : selfName] - linkA.style.marginRight = pxround( - ((rightMetrics.advance / 2) * kSVGScale * lilScale) - (kLinkAWidth / 2) - ) + 'px' - } else { - linkA.style.marginLeft = pxround( - ((leftMetrics.advance / 2) * kSVGScale * lilScale) - (kLinkAWidth / 2) - ) + 'px' - } - - pair.appendChild(link) - } - - - kerningList.appendChild(pair) - }) - - return keys.length != 0 - } - - var selfLeft = mkpairGlyph(g.name, 'left', 0, thisSvgURI) - var selfRight = mkpairGlyph(g.name, 'right', 0, thisSvgURI) - - if (mkpairs(kerningAsLeft, g.name, selfLeft, 'left') && - kerningAsRightKeys.length != 0) - { - var div = document.createElement('div') - div.className = 'divider' - kerningList.appendChild(div) - } - - mkpairs(kerningAsRight, g.name, selfRight, 'right') - - if (location.hash && location.hash.indexOf('#kern') == 0) { - var id = location.hash.substr(1) - setTimeout(function(){ - selectKerningPair(id) - },1) - } - - kerningList.style.display = null - return true -} - - -function fmthex(cp, minWidth) { - let s = cp.toString(16).toUpperCase() - while (s.length < minWidth) { - s = '0' + s - } - return s -} - - -// hook up glyph table click handlers -function onClickGlyphInTable(ev) { - // let le = ev.target - document.location.href = "?g=" + encodeURI(ev.target.dataset.glyphname) -} -const activeListener = { capture: true } -let cv = document.querySelector('.charset-table').querySelectorAll('c') -for (let i = 0; i < cv.length; i++) { - let c = cv[i] - if (typeof PointerEvent == "undefined") { - c.addEventListener('mousedown', onClickGlyphInTable, activeListener) - } else { - c.addEventListener('pointerdown', onClickGlyphInTable, activeListener) - } -} -// document.location.href = "/glyphs/?g=" + encodeURI(ev.target.dataset.glyphname) - - -updateLocation() |