summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Andersson <rasmus@notion.se>2018-02-20 12:38:51 +0300
committerRasmus Andersson <rasmus@notion.se>2018-02-20 12:38:51 +0300
commit9f367901ef4e6df00eb786ac99fcdc21ed5e69f0 (patch)
tree44ea3e320dd96f541ed94f5a032bff70050afc51
parent761638ef42ec443429889c548b758c06a516839a (diff)
downloadinter-9f367901ef4e6df00eb786ac99fcdc21ed5e69f0.tar.xz
website: major update
-rw-r--r--.gitignore1
-rw-r--r--Makefile6
-rw-r--r--docs/_config.yml10
-rw-r--r--docs/_data/fontinfo.json (renamed from docs/info.json)9
-rw-r--r--docs/_includes/autoreload-in-debug.html46
-rw-r--r--docs/_layouts/default.html88
-rwxr-xr-xdocs/_scripts/optimize-resources.sh (renamed from docs/optimize-resources.sh)2
-rwxr-xr-xdocs/_scripts/serve.sh9
-rw-r--r--docs/dynmetrics/index.css262
-rw-r--r--docs/dynmetrics/index.html522
-rw-r--r--docs/glyphs/index.html111
-rw-r--r--docs/index.html686
-rw-r--r--docs/index.js138
-rw-r--r--docs/res/base.css (renamed from docs/index.css)224
-rw-r--r--docs/res/base.js74
-rw-r--r--docs/res/bindings.js (renamed from docs/samples/bindings.js)40
-rw-r--r--docs/res/favicon.png (renamed from docs/favicon.png)bin700 -> 700 bytes
-rw-r--r--docs/res/graphplot.js239
-rw-r--r--docs/samples/index.css243
-rw-r--r--docs/samples/index.html524
-rwxr-xr-xdocs/serve.sh24
-rwxr-xr-xmisc/fontinfo.py13
22 files changed, 2190 insertions, 1081 deletions
diff --git a/.gitignore b/.gitignore
index b3a43f28a..57e02b3ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ nohup.out
build
/_*
/docs/lab/fonts
+/docs/_site
src/FontInspector.html
src/svg
diff --git a/Makefile b/Makefile
index 66eac073c..82a12ecbe 100644
--- a/Makefile
+++ b/Makefile
@@ -159,13 +159,13 @@ install_otf: all_otf
install: install_otf
-geninfo: docs/info.json docs/lab/glyphinfo.json docs/glyphs/metrics.json
+geninfo: docs/_data/fontinfo.json docs/lab/glyphinfo.json docs/glyphs/metrics.json
src/glyphorder.txt: src/Inter-UI-Regular.ufo/lib.plist src/Inter-UI-Black.ufo/lib.plist src/diacritics.txt misc/gen-glyphorder.py
misc/gen-glyphorder.py src/Inter-UI-*.ufo > src/glyphorder.txt
-docs/info.json: misc/fontinfo.py docs/font-files/Inter-UI-*.otf
- misc/fontinfo.py -pretty docs/font-files/Inter-UI-Regular.otf > docs/info.json
+docs/_data/fontinfo.json: misc/fontinfo.py docs/font-files/Inter-UI-*.otf
+ misc/fontinfo.py -pretty docs/font-files/Inter-UI-Regular.otf > docs/_data/fontinfo.json
docs/lab/glyphinfo.json: _local/UnicodeData.txt src/glyphorder.txt src/fontbuild.cfg misc/gen-glyphinfo.py
misc/gen-glyphinfo.py -ucd _local/UnicodeData.txt \
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 000000000..f00875d90
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,10 @@
+port: 3000
+lsi: false
+permalink: /:title
+markdown: kramdown
+# Since GH pages override this to "true", we test this value to see if we are running locally
+safe: false
+kramdown:
+ input: GFM
+ auto_ids: true
+ hard_wrap: false
diff --git a/docs/info.json b/docs/_data/fontinfo.json
index 97fde5b79..6d4e8c038 100644
--- a/docs/info.json
+++ b/docs/_data/fontinfo.json
@@ -1,5 +1,5 @@
-{
- "Inter UI Regular:2018:86daccf": {
+[
+ {
"head": {
"checkSumAdjustment": 3690365233,
"created": 3563720514,
@@ -117,6 +117,7 @@
"minMemType42": 0,
"underlinePosition": -422,
"underlineThickness": 170
- }
+ },
+ "version": "2.5"
}
-} \ No newline at end of file
+]
diff --git a/docs/_includes/autoreload-in-debug.html b/docs/_includes/autoreload-in-debug.html
new file mode 100644
index 000000000..13840defa
--- /dev/null
+++ b/docs/_includes/autoreload-in-debug.html
@@ -0,0 +1,46 @@
+{% if site.safe == false %}
+<!-- During authoring, this automatically reloads the post as its changing -->
+<script type="text/javascript">
+(function() {
+var qs = document.location.search;
+var current_etag = qs.match(/etag=("?[a-zA-Z0-9_-]+)/);
+if (current_etag !== null) { current_etag = current_etag[1]; }
+var scrolly = qs.match(/scrolly=([0-9]+)/);
+if (scrolly) {
+ scrolly = parseInt(scrolly[1]);
+ if (scrolly > 0) {
+ window.scrollTo(window.scrollX, scrolly);
+ setTimeout(function () {
+ window.scrollTo(window.scrollX, scrolly);
+ }, 10);
+ }
+}
+
+function check() {
+ var r = new XMLHttpRequest();
+ var url = document.location.href + ((qs && qs !== '') ? '&' : '?') + 'r=' + Math.random();
+ r.open('GET', url, true);
+ r.onreadystatechange = function() {
+ if (r.readyState == 4){
+ var found_etag = r.getResponseHeader('Etag');
+ if (found_etag) {
+ found_etag = found_etag.replace(/^"|"$/g);
+ }
+ //console.log('current_etag:', current_etag, 'found_etag:', found_etag);
+ if (current_etag === null) {
+ current_etag = found_etag;
+ } else if (found_etag !== current_etag) {
+ document.location.search =
+ '?etag=' + encodeURIComponent(found_etag) +
+ '&scrolly=' + window.scrollY;
+ return;
+ }
+ setTimeout(check, 500);
+ }
+ };
+ r.send(null);
+}
+check();
+})();
+</script>
+{% endif %} \ No newline at end of file
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
new file mode 100644
index 000000000..d694ce3bd
--- /dev/null
+++ b/docs/_layouts/default.html
@@ -0,0 +1,88 @@
+{%
+assign build_version = site.time | date: "%Y%m%d%H%M%S" %}{%
+assign description = "Inter UI is a new typeface optimized for computer user interfaces" %}{%
+
+capture url_root
+ %}{% if site.safe == false %}/{% else %}/inter/{% endif
+%}{%
+endcapture %}{%
+
+capture release_version
+ %}{{ site.data.fontinfo[0].version }}{%
+endcapture %}{%
+
+capture download_url
+ %}https://github.com/rsms/inter/releases/download/v{{ release_version }}/Inter-UI-{{ release_version }}.zip{%
+endcapture %}{%
+
+for file in site.static_files %}{%
+ assign _path = file.path | remove_first: "/inter" %}{%
+ if _path == "/res/base.css" %}{%
+ assign base_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/res/base.js" %}{%
+ assign base_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ endif %}{%
+endfor
+
+%}<!DOCTYPE HTML>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>{% if page.title %}{{ page.title }} — Inter UI{% else %}Inter UI font family{% endif %}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <link rel="stylesheet" href="{{url_root}}inter-ui.css?v={{ release_version }}">
+ <link rel="stylesheet" href="{{url_root}}res/base.css?v={{ base_css_v }}">
+ <link rel="icon" type="image/png" href="{{url_root}}res/favicon.png">
+ <meta name="format-detection" content="telephone=no">
+ <meta property="twitter:card" content="summary">
+ <meta property="twitter:site" content="@rsms">
+ <meta property="twitter:creator" content="@rsms">
+ <meta property="description" content="{{description}}">
+ <meta property="og:description" content="{{description}}">
+ <meta property="twitter:description" content="{{description}}">
+ {% if page.title %}
+ <meta property="og:title" content="{{ page.title }}">
+ <meta property="twitter:title" content="{{ page.title }}">
+ {% endif %}
+ {% if page.og_image_url %}
+ <meta property="og:image" content="{{ page.og_image_url }}">
+ <meta property="twitter:image" content="{{ page.og_image_url }}">
+ {% else %}
+ <meta property="og:image" content="https://rsms.me/inter/res/poster.png">
+ <meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
+ {% endif %}
+ <meta property="og:url" content="https://rsms.me/inter/{{ page.url | remove_first:'index.html' }}">
+ <meta property="fb:app_id" content="38027689216">
+ <meta property="og:site_name" content="rsms.me/inter">
+ <meta property="og:type" content="product">
+ <meta property="og:locale" content="en_US" />
+ </head>
+ <body>
+ <script src="{{url_root}}res/base.js?v={{ base_js_v }}"></script>
+
+ <div class="row menu">
+ <ul class="menu">
+ <li class="home"><a href="{{url_root}}">Inter UI</a></li>
+ <li><a class="download-link" href="{{ download_url }}"
+ >Download</a></li>
+ <li><a href="{{url_root}}samples/"
+ {% if page.url contains "/samples/" %}class="active"{% endif %}
+ >Samples</a></li>
+ <li><a href="{{url_root}}lab/"
+ {% if page.url contains "/lab/" %}class="active"{% endif %}
+ >Playground</a></li>
+ <li><a href="https://github.com/rsms/inter/"
+ >Source</a></li>
+ </ul>
+ </div>
+
+ {{ content }}
+
+ {% if site.safe == true %}
+ <script async src="https://www.googletagmanager.com/gtag/js?id=UA-105091131-2"></script>
+ {% endif %}
+ {% include autoreload-in-debug.html %}
+ </body>
+</html>
diff --git a/docs/optimize-resources.sh b/docs/_scripts/optimize-resources.sh
index b539d0775..72d45b9f1 100755
--- a/docs/optimize-resources.sh
+++ b/docs/_scripts/optimize-resources.sh
@@ -1,6 +1,6 @@
#!/bin/sh
set -e
-cd "$(dirname "$0")"
+cd "$(dirname "$0")/.."
pushd res >/dev/null
diff --git a/docs/_scripts/serve.sh b/docs/_scripts/serve.sh
new file mode 100755
index 000000000..a319d8e22
--- /dev/null
+++ b/docs/_scripts/serve.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+cd "$(dirname "$0")/.."
+
+if [ ! -s lab/fonts ]; then
+ ln -s ../../build/dist lab/fonts
+fi
+
+jekyll serve --limit_posts 20 --watch --host 127.0.0.1 --port 3002 --open-url
diff --git a/docs/dynmetrics/index.css b/docs/dynmetrics/index.css
new file mode 100644
index 000000000..c7c98d351
--- /dev/null
+++ b/docs/dynmetrics/index.css
@@ -0,0 +1,262 @@
+body {
+ padding-bottom: 0;
+}
+
+const {
+ display: inline;
+ font-size: 1.2em;
+ font-style: italic;
+ font-family: 'Times New Roman', Times, serif;
+}
+
+sup {
+ /*background:lightpink;*/
+ display: inline-block;
+ font-size:0.92em;
+ position: relative;
+ top:-0.4em;
+ letter-spacing: 0.001em;
+ vertical-align: baseline;
+}
+
+.row.first {
+ padding-bottom:1em;
+}
+
+formula {
+ display: inline-flex;
+ align-items: center;
+ background: white;
+ border-radius: 5px;
+ padding: 0 1em;
+ line-height: 3em;
+ height: 3em;
+ overflow: hidden;
+ margin-right: 1em;
+ margin-bottom: 1em;
+}
+.row.white formula {
+ background: #f5f5f5;
+}
+formula:last-child {
+ margin-right: 0;
+}
+formula.code {
+ white-space: pre;
+ font-family: "SFMono-Regular", Menlo, Consolas, Inconsolata, monospace;
+ font-size:0.96em;
+}
+ formula > * {
+ margin: 0 0.2em 0 0.2em;
+ }
+ formula > const {
+ margin-bottom: 0.11em;
+ }
+ formula > sup {
+ margin-left: 0;
+ }
+
+
+.samples {
+ display: flex;
+ flex-wrap: wrap;
+ overflow: auto;
+ overflow-wrap: break-word;
+ word-break: break-word;
+}
+ .samples .sample {
+ /*background: lightpink;*/
+ color: #111;
+ flex: 0 1 auto;
+ outline: none;
+ margin-right: 50px;
+ margin-bottom: 50px;
+ }
+ .samples .sample .di {
+ display: block;
+ background-color: #ccc;
+ height: 1px;
+ width: 100%;
+ margin-bottom: 8px;
+ }
+ .samples .sample .di > span {
+ display: block;
+ background-color: #333;
+ height: 100%;
+ }
+ .samples .sample .di.match > span {
+ background-color: #0d3;
+ }
+ .samples .sample .di.unavailable {
+ background-color: #eee;
+ }
+ .samples .sample .di.unavailable > span {
+ visibility: hidden;
+ }
+ .samples .sample .info {
+ display: block;
+ font-size: 11px !important;
+ line-height: 11px;
+ margin-bottom: 9px;
+ color: #bbb;
+ }
+
+
+.font-style-regular { font-weight:400 !important; font-style:normal !important; }
+.font-style-italic { font-weight:400 !important; font-style:italic !important; }
+.font-style-medium { font-weight:500 !important; font-style:normal !important; }
+.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
+.font-style-bold { font-weight:700 !important; font-style:normal !important; }
+.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
+.font-style-black { font-weight:900 !important; font-style:normal !important; }
+.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
+
+.row.with-sidebar {
+ padding: 0;
+}
+ .row.with-sidebar > *:first-child {
+ flex: 1 1 auto;
+ padding: 50px 0 0 50px; /* note: samples have 50px right margin */
+ }
+ .row.with-sidebar > .sidebar {
+ flex: 0 0 auto;
+ }
+
+div.controls {
+ box-sizing: border-box;
+ width: 250px;
+ max-width: 250px;
+ flex: 0 0 auto;
+ padding: 10px 0;
+ border-left: 4px solid #f4f4f4;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+div.controls hr {
+ border: none;
+ height: 2px;
+ background: #f4f4f4;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+div.controls hr.without-bottom-margin { margin-bottom: 0; }
+div.controls hr.without-top-margin { margin-top: 0; }
+div.controls hr.without-margins { margin: 0; }
+div.controls .control {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ overflow: hidden;
+ height: 30px;
+ margin: 0 16px;
+}
+div.controls > h3 {
+ margin: 0 16px;
+}
+div.controls > textarea {
+ border: none;
+ padding:16px;
+ height: 400px;
+ font-family: "SFMono-Regular", Menlo, Consolas, Inconsolata, monospace;
+ outline: none;
+}
+div.controls .control > * {
+ /*max-width: 50%;*/
+ flex: 1 1 auto;
+ margin:0;
+ margin-right: 16px;
+ box-sizing: border-box;
+}
+div.controls .control > :last-child {
+ margin-right: 0;
+}
+div.controls .control > select {
+ min-width: 6em;
+ align-items: center;
+ justify-content: center;
+}
+div.controls .control > input,
+div.controls .control > select {
+ width: 0;
+ outline: none;
+}
+div.controls .control > input[type="number"],
+div.controls .control > input[type="text"] {
+ background: none;
+ border: none;
+ padding: 4px 0;
+ font-size: 13px;
+}
+div.controls .control > input[type="number"] {
+ max-width: 60px;
+ -moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+}
+div.controls .control > input[type=number]::-webkit-inner-spin-button,
+div.controls .control > input[type=number]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+div.controls .control > input[type="number"][readonly] {
+ max-width: 40px;
+}
+div.controls .control > input.wide[type="number"] {
+ max-width: 100%;
+}
+div.controls .control > input[type="range"] {
+ /*max-width: 80%;*/
+ flex: 1 1 auto;
+ display: block;
+}
+div.controls .control > img.icon,
+div.controls .control > label {
+ font-family: georgia, serif;
+ font-style: italic;
+ line-height: 16px;
+ color: black;
+ width: 16px;
+ height: 16px;
+ flex: 0 0 auto;
+ margin-right: 16px;
+ opacity: 0.6;
+}
+div.controls canvas {
+ height: 200px;
+}
+
+.row.small-window {
+ margin-top:0;
+ padding-top:0;
+}
+
+@media only screen and (min-width: 541px) {
+ .small-window {
+ display: none;
+ }
+}
+
+@media only screen and (max-width: 540px) {
+
+ .row.with-sidebar {
+ overflow: auto;
+ }
+
+ div.controls {
+ display: none;
+ }
+ div.controls .graphplot,
+ div.controls hr.without-top-margin,
+ div.controls h3,
+ div.controls #ideal-values
+ {
+ display: none;
+ }
+
+ .row.with-sidebar {
+ flex-direction: column;
+ }
+}
diff --git a/docs/dynmetrics/index.html b/docs/dynmetrics/index.html
new file mode 100644
index 000000000..21bd95d82
--- /dev/null
+++ b/docs/dynmetrics/index.html
@@ -0,0 +1,522 @@
+---
+layout: default
+title: Dynamic Metrics
+---
+{%
+
+capture url_root
+ %}{% if site.safe == false %}/{% else %}/inter/{% endif
+%}{%
+endcapture %}{%
+
+for file in site.static_files %}{%
+ assign _path = file.path | remove_first: "/inter" %}{%
+ if _path == "/dynmetrics/index.css" %}{%
+ assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/res/bindings.js" %}{%
+ assign bindings_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/res/graphplot.js" %}{%
+ assign graphplot_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ endif %}{%
+endfor
+
+%}
+<link rel="stylesheet" href="index.css?v={{ index_css_v }}">
+<script src="{{url_root}}res/bindings.js?v={{ bindings_js_v }}"></script>
+<script src="{{url_root}}res/graphplot.js?v={{ graphplot_js_v }}"></script>
+
+<div class="row first"><div>
+ <h1>Dynamic Metrics</h1>
+ <p>
+ There's of course no absolute right or wrong when it comes to expressing
+ yourself with typography, but Inter UI Dynamic Metrics provides guidelines
+ for <em>good</em> typography.
+ You simply provide the optical font size, and the tracking and leading
+ (letter spacing and line height) will be calculated using the following
+ formula:
+ </p>
+ <p>
+ <formula>
+ tracking =
+ <const>a</const> + <const>b</const> ×
+ <const>e</const><sup>(<const>c</const> × fontSize)</sup>
+ </formula>
+ <formula>
+ leading = <const>l</const> × fontSize
+ </formula>
+ <formula>
+ <const>e</const> ≈ <num>2.718</num>
+ </formula>
+ </p>
+ <p class="small-window">
+ <small>View this on a larger screen to enable interactive control.</small>
+ </p>
+</div></div>
+
+<!-- <div class="row small-window"><div>
+ Hello
+</div></div> -->
+
+<div class="white full-width row with-sidebar">
+
+ <div class="samples">
+ <p contenteditable class="sample">
+ <span class="di"><span></span></span>
+ <span class="info"
+ title="size, tracking, (ideal tracking) — progress bar shows distance from ideal"
+ >15 &nbsp; 0.0 &nbsp; ( 0.0 )</span>
+ Such a riot of sea and wind strews the whole extent of beach with whatever has been lost or thrown overboard, or torn out of sunken ships. Many a man has made a good week’s work in a single day by what he has found while walking along the Beach when the surf was down.
+ </p>
+ </div>
+
+ <div class="sidebar controls">
+ <div class="control">
+ <label title="Number of ideal matches">ni</label>
+ <input title="Number of ideal matches" type="number" readonly data-binding="ideal-count">
+ <label title="Distance from ideal">di</label>
+ <input title="Distance from ideal" type="number" class="wide" readonly data-binding="ideal-distance">
+ </div>
+ <div class="control">
+ <img title="Style" class="icon" src="../samples/icons/style.svg">
+ <select data-binding="style">
+ <option value="regular" default>Regular</option>
+ <option value="italic">Italic</option>
+ <option value="medium" default>Medium</option>
+ <option value="medium-italic">Medium Italic</option>
+ <option value="bold" default>Bold</option>
+ <option value="bold-italic">Bold Italic</option>
+ <option value="black" default>Black</option>
+ <option value="black-italic">Black Italic</option>
+ </select>
+ </div>
+ <div class="control">
+ <img title="Base tracking" class="icon" src="../samples/icons/letter-spacing.svg">
+ <input type="range" min="-0.05" max="0.06" step="0.001" data-binding="base-tracking">
+ <input type="number" min="-0.15" max="1" step="0.001" data-binding="base-tracking">
+ </div>
+ <hr>
+ <div class="control">
+ <label title="Constant a">a</label>
+ <input type="range" min="-0.05" max="0" step="0.001" data-binding="var-a">
+ <input type="number" min="-0.05" max="0" step="0.0001" data-binding="var-a">
+ </div>
+ <div class="control">
+ <label title="Constant b">b</label>
+ <input type="range" min="0" max="1" step="0.01" data-binding="var-b">
+ <input type="number" min="0" max="1" step="0.001" data-binding="var-b">
+ </div>
+ <div class="control">
+ <label title="Constant c">c</label>
+ <input type="range" min="-1" max="0" step="0.01" data-binding="var-c">
+ <input type="number" min="-1" max="0" step="0.001" data-binding="var-c">
+ </div>
+ <hr>
+ <div class="control">
+ <label title="Constant l controls line height">l</label>
+ <input type="range" min="1" max="2" step="0.1" data-binding="var-l">
+ <input type="number" min="1" max="2" step="0.1" data-binding="var-l">
+ </div>
+ <hr class="without-bottom-margin">
+ <canvas class="graphplot">Canvas not Supported</canvas>
+ <hr class="without-top-margin">
+ <h3>Ideal values</h3>
+ <textarea id="ideal-values"></textarea>
+ <hr class="without-top-margin">
+ </div>
+
+</div>
+
+
+<script type="text/javascript">(function(){
+
+// internal variables that are user-controllable, but are not part of
+// Dynamic Metrics
+var baseTracking = 0
+var weightClass = 400
+
+// Ideal values designed one by one, by hand.
+// font size => tracking
+var idealValues = {}
+var idealValuesList = []
+var idealValuesTextArea = $('textarea#ideal-values')
+
+function setIdealValues(valueMap) {
+ idealValues = valueMap
+ idealValuesList = []
+ Object.keys(idealValues).forEach(function(fontSize) {
+ idealValuesList.push([fontSize, idealValues[fontSize]])
+ })
+ if (idealValuesTextArea.value == '') {
+ idealValuesTextArea.value = idealValuesList.map(function(t){
+ return t[0] + '\t' + t[1]
+ }).join('\n')
+ }
+}
+
+function parseValues(s) {
+ var values = {}
+ s = s.replace(/^[\s\r\t\n]+|[\s\r\t\n]+$/g, '') // trim whitespace
+ s.split(/\s*\r?\n\s*/).map(function(line) {
+ var t = line.split(/\s+/)
+ if (t.length == 2) {
+ t[0] = parseInt(t[0])
+ t[1] = parseFloat(t[1])
+ values[t[0]] = t[1]
+ }
+ })
+ return values
+}
+
+setIdealValues({
+ // set-2018-02-20
+ 6: 0.055,
+ 7: 0.044,
+ 8: 0.034,
+ 9: 0.024,
+ 10: 0.018,
+ 11: 0.012,
+ 12: 0.007,
+ 13: 0.003,
+ 14: 0.001,
+ 15: -0.002,
+ 16: -0.004,
+ 17: -0.006,
+ 18: -0.008,
+ 20: -0.01,
+ 24: -0.013,
+})
+
+// setIdealValues({
+// // set-2018-02-19
+// 6: 0.059,
+// 7: 0.043,
+// 8: 0.032,
+// 9: 0.022,
+// 10: 0.014,
+// 11: 0.009,
+// 12: 0.004,
+// 13: 0,
+// 14: -0.003,
+// 15: -0.005,
+// 16: -0.0075,
+// 17: -0.0084,
+// 18: -0.0095,
+// 20: -0.012,
+// 24: -0.014,
+// })
+
+// setIdealValues({
+// // set-2018-02-18
+// 6: 0.06,
+// 7: 0.04,
+// 8: 0.03,
+// 9: 0.02,
+// 10: 0.01,
+// 11: 0.005,
+// 12: 0.002,
+// 13: 0.001,
+// 14: 0,
+// 15: -0.002,
+// 16: -0.005,
+// 17: -0.007,
+// 18: -0.009,
+// 20: -0.011,
+// 24: -0.011,
+// })
+
+
+// Variables for constants involved in Dynamic Metrics
+var a = -0.013
+// -0.0119
+// -0.0101
+// -0.0092
+// -0.012
+// -0.013
+
+var b = 0.23
+// 0.455
+// 0.421
+// 0.26
+// 0.23
+// 0.251
+
+var c = -0.21
+// -0.29
+// -0.23
+// -0.21
+// -0.222
+
+// a = -0.012; b = 0.23; c = -0.21; // di=0.002514 on set-2018-02-18
+// a = -0.013; b = 0.251; c = -0.222 // di=0.001742 on set-2018-02-18
+// a = -0.015; b = 0.283; c = -0.23; // di=0.00221 on set-2018-02-18
+// a = -0.0149; b = 0.298; c = -0.23; // di=0.000484 on set-2018-02-19
+a = -0.016; b = 0.21; c = -0.18; // di=0.000532 on set-2018-02-20
+
+
+// these have a short di, but stray far away from larger font sizes
+// a = -0.0077
+// b = 0.377
+
+var l = 1.4
+
+
+// InterUIDynamicTracking takes the font size in points or pixels and returns
+// the compensating tracking in EM.
+//
+function InterUIDynamicTracking(fontSize, weightClass) {
+ // if (!weightClass) { -- currently unused
+ // weightClass = 400
+ // }
+ //
+ // y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
+ // [6-35] 0.05877 .. -0.0101309 (13==0; stops growing around 30-35)
+ // See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
+ //
+ return a + b * Math.pow(Math.E, c * fontSize)
+ // [6 - 38] 0.05798 .. -0.01099 (midpoint = 12.533)
+
+ // y = 0.025 - (ln(x) * 0.01)
+ // return 0.025 - Math.log(fontSize) * 0.01
+}
+
+
+function InterUIDynamicLineHeight(fontSize, weightClass) {
+ return Math.round(fontSize * l)
+}
+
+
+var NPOS = Number.MAX_SAFE_INTEGER
+
+function Sample(fontSize) {
+ this.rootEl = sampleTemplate.cloneNode(true)
+ this.infoEl = $('.info', this.rootEl)
+ this.diEl = $('.di', this.rootEl)
+ this.diEl.classList.add('unavailable')
+ this.style = this.rootEl.style
+ this.maxBoxWidth = 0
+ this.fontSize = 0
+ this.tracking = 0
+ this.lineHeight = 0
+ this.idealTracking = NPOS
+ this.matchesIdeal = false
+ this.setFontSize(fontSize)
+ this.render()
+}
+
+Sample.prototype.idealDistance = function(fontSize) {
+ // returns the distance from the ideal (or NPOS if no "ideal" data available)
+ if (this.idealTracking == NPOS) {
+ return NPOS
+ }
+ return (
+ Math.max(this.tracking, this.idealTracking) -
+ Math.min(this.tracking, this.idealTracking)
+ )
+}
+
+Sample.prototype.setFontSize = function(fontSize) {
+ this.fontSize = fontSize
+ this.tracking = baseTracking + InterUIDynamicTracking(fontSize, weightClass)
+ this.lineHeight = InterUIDynamicLineHeight(fontSize, weightClass)
+ this.maxBoxWidth = Math.round(fontSize * (this.tracking + 1) * 25)
+
+ var idealTracking = idealValues[this.fontSize]
+ if (idealTracking === undefined) {
+ if (this.idealTracking != NPOS) {
+ this.diEl.classList.add('unavailable')
+ }
+ this.idealTracking = NPOS
+ this.matchesIdeal = false
+ } else {
+ if (this.idealTracking == NPOS) {
+ this.diEl.classList.remove('unavailable')
+ }
+ this.idealTracking = idealTracking
+ // match to a precision of 3
+ this.matchesIdeal = this.tracking.toFixed(3) == idealTracking.toFixed(3)
+ var di = 1
+ if (this.matchesIdeal) {
+ this.diEl.classList.add('match')
+ } else {
+ this.diEl.classList.remove('match')
+ di = 1 - Math.min(1, this.idealDistance() * 50)
+ }
+ this.diEl.firstChild.style.width = (di * this.maxBoxWidth) + 'px'
+ }
+}
+
+Sample.prototype.render = function() {
+ this.style.fontSize = this.fontSize + 'px'
+ this.style.letterSpacing = this.tracking + 'em'
+ this.style.lineHeight = this.lineHeight + 'px'
+
+ var SP = '\u00A0\u00A0\u00A0'
+ this.infoEl.innerText = (
+ this.fontSize +
+ SP + this.tracking.toFixed(3) +
+ // SP + this.lineHeight.toFixed(3) +
+ (
+ this.idealTracking != NPOS ? (
+ SP + '( ' + this.idealTracking +
+ (this.matchesIdeal ? ' \u2713' : '') +
+ ' )'
+ ) : ''
+ )
+ )
+
+ this.style.maxWidth = this.maxBoxWidth + 'px'
+}
+
+
+var bindings = new Bindings()
+var sampleTemplate
+var samples = [] // Sample[]
+var graph = new GraphPlot($('canvas.graphplot'))
+graph.setOrigin(-0.2, 0.8)
+graph.setScale(0.049, 5)
+
+function addChildren(targetNode, children) {
+ targetNode.style.visibility = 'hidden'
+ var i = 0;
+ for (; i < children.length; i++) {
+ targetNode.appendChild(children[i])
+ }
+ targetNode.style.visibility = null
+}
+
+function initSamples() {
+ var samplesEl = $('.samples')
+ sampleTemplate = $('.sample', samplesEl)
+ samplesEl.removeChild(sampleTemplate)
+
+ // small and medium sizes
+ var i, fontSize = 6, endFontSize = 16
+ for (; fontSize <= endFontSize; fontSize++) {
+ samples.push(new Sample(fontSize))
+ }
+
+ // a few select large samples
+ samples.push(new Sample(17))
+ samples.push(new Sample(18))
+ samples.push(new Sample(20))
+ samples.push(new Sample(24))
+ samples.push(new Sample(30))
+ samples.push(new Sample(40))
+
+ // add to dom in one go
+ addChildren(samplesEl, samples.map(function(s) { return s.rootEl }))
+}
+
+
+function updateSample(sample) {
+ sample.setFontSize(sample.fontSize) // updates derived values
+ sample.render()
+}
+
+function updateSamples() {
+ samples.forEach(updateSample)
+ updateIdealMatches()
+ updateGraphPlot()
+}
+
+function updateIdealMatches() {
+ // ideal-distance
+ var idealCount = 0
+ var distance = 0
+ var ndistances = 0
+ samples.forEach(function(sample) {
+ if (sample.matchesIdeal) {
+ idealCount++
+ }
+ var di = sample.idealDistance()
+ if (di != NPOS) {
+ distance += di
+ ndistances++
+ }
+ })
+
+ distance = distance / ndistances
+
+ bindings.setValue('ideal-distance', distance.toFixed(6))
+ bindings.setValue('ideal-count', idealCount)
+}
+
+function updateGraphPlot() {
+ graph.clear()
+ graph.plotLine(idealValuesList, '#0d3')
+ graph.plotf(function(x) {
+ return InterUIDynamicTracking(x, weightClass)
+ })
+}
+
+
+bindings.configure('base-tracking', 0, 'float', function (tracking) {
+ baseTracking = tracking
+ updateSamples()
+})
+
+bindings.configure('var-a', a, 'float', function (v) {
+ a = v
+ updateSamples()
+})
+
+bindings.configure('var-b', b, 'float', function (v) {
+ b = v
+ updateSamples()
+})
+
+bindings.configure('var-c', c, 'float', function (v) {
+ c = v
+ updateSamples()
+})
+
+bindings.configure('var-l', l, 'float', function (v) {
+ l = v
+ updateSamples()
+})
+
+bindings.configure('ideal-count', 0, 'int', function (v) {})
+bindings.configure('ideal-distance', 0, 'float', function (v) {})
+
+bindings.configure('style', null, null, function (style) {
+ var cl = $('.samples').classList
+ cl.remove('font-style-regular')
+ cl.remove('font-style-italic')
+ cl.remove('font-style-medium')
+ cl.remove('font-style-medium-italic')
+ cl.remove('font-style-bold')
+ cl.remove('font-style-bold-italic')
+ cl.remove('font-style-black')
+ cl.remove('font-style-black-italic')
+ cl.add('font-style-' + style)
+ weightClass = (
+ style.indexOf('black') != -1 ? 900 :
+ style.indexOf('bold') != -1 ? 700 :
+ style.indexOf('medium') != -1 ? 500 :
+ 400
+ )
+ updateSamples()
+})
+
+
+bindings.bindAllInputs('.control input')
+bindings.bindAllInputs('.control select')
+
+// double-click base tracking to reset
+$('input[type="range"][data-binding="base-tracking"]').addEventListener(
+ 'dblclick',
+ function(ev) { bindings.setValue('base-tracking', 0) }
+)
+
+// allow editing of ideal values
+idealValuesTextArea.addEventListener('input', function(ev) {
+ setIdealValues(parseValues(idealValuesTextArea.value))
+ updateSamples()
+})
+
+
+// start
+initSamples()
+updateSamples()
+
+})();</script>
diff --git a/docs/glyphs/index.html b/docs/glyphs/index.html
index aa5faeff2..3a47285bb 100644
--- a/docs/glyphs/index.html
+++ b/docs/glyphs/index.html
@@ -1,39 +1,27 @@
-<!DOCTYPE HTML>
-<html lang="en" prefix="og: http://ogp.me/ns#">
- <head>
- <meta charset="utf-8">
- <title>Repertoire – Inter UI font family</title>
+---
+layout: default
+title: Glyphs
+---
+{%
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
+capture url_root
+ %}{% if site.safe == false %}/{% else %}/inter/{% endif
+%}{%
+endcapture %}{%
- <meta property="og:title" content="Inter UI font family">
- <meta property="twitter:title" content="Inter UI font family">
- <meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:card" content="summary">
- <meta property="twitter:site" content="@rsms">
- <meta property="twitter:creator" content="@rsms">
- <meta property="og:image" content="https://rsms.me/inter/res/poster.png">
- <meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
+for file in site.static_files %}{%
+ assign _path = file.path | remove_first: "/inter" %}{%
+ if _path == "/glyphs/glyphs.css" %}{%
+ assign glyphs_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/glyphs/glyphs.js" %}{%
+ assign glyphs_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ endif %}{%
+endfor
- <meta property="fb:app_id" content="38027689216">
- <meta property="fb:admins" content="728642302">
- <meta property="og:url" content="https://rsms.me/inter/">
- <meta property="og:site_name" content="rsms.me">
- <meta property="og:type" content="product">
- <meta property="og:locale" content="en_US" />
+%}
- <link rel="icon" type="image/png" href="../favicon.png" />
-
- <link href="../inter-ui.css" rel="stylesheet">
- <link href="../index.css" rel="stylesheet">
- <link href="glyphs.css" rel="stylesheet">
- </head>
- <body>
- <script src="../index.js"></script>
- <div id="svgs">
+<link rel="stylesheet" href="glyphs.css?v={{ glyphs_css_v }}">
+<div id="svgs">
<svg id="svg-A" xmlns="http://www.w3.org/2000/svg" width="176" height="348"><path d="M146 -76.8 L44.8 -76.8 L44.8 -54.8 L146 -54.8z M33.2 0 L94 -172.4 L96.4 -172.4 L157.2 0 L183.2 0 L108 -204.8 L82.4 -204.8 L7.2 0z" transform="translate(-7.2 281.6)"/></svg>
<svg id="svg-AE" xmlns="http://www.w3.org/2000/svg" width="264" height="348"><path d="M142.4 -186 L144.8 -204.8 L127.2 -204.8 L6 0 L35.6 0z M164 -76.8 L60.4 -76.8 L60.4 -55.2 L164 -55.2z M269.2 -22 L168.4 -22 L168.4 0 L269.2 0z M164.8 -204.8 L140.4 -204.8 L148.8 0 L173.2 0z M249.6 -115.2 L162.8 -115.2 L162.8 -93.2 L249.6 -93.2z M260.8 -204.8 L160 -204.8 L160 -182.8 L260.8 -182.8z" transform="translate(-6 281.6)"/></svg>
<svg id="svg-AEacute" xmlns="http://www.w3.org/2000/svg" width="264" height="348"><path d="M142.4 -186 L144.8 -204.8 L127.2 -204.8 L6 0 L35.6 0z M164 -76.8 L60.4 -76.8 L60.4 -55.2 L164 -55.2z M269.2 -22 L168.4 -22 L168.4 0 L269.2 0z M164.8 -204.8 L140.4 -204.8 L148.8 0 L173.2 0z M249.6 -115.2 L162.8 -115.2 L162.8 -93.2 L249.6 -93.2z M260.8 -204.8 L160 -204.8 L160 -182.8 L260.8 -182.8z M135.2 -223.2 L152.8 -223.2 L183.6 -264 L159.2 -264z" transform="translate(-6 281.6)"/></svg>
@@ -2222,37 +2210,34 @@
<svg id="svg-zrthook" xmlns="http://www.w3.org/2000/svg" width="151" height="348"><path d="M112.8 -16.8 L112.8 19.2 C112.8 45.6 130.4 60 153.2 60 C157.6 60 163.2 59.6 166.8 58.4 L166.8 38 C164.8 38.8 161.2 38.8 159.2 38.8 C146.4 38.8 136.4 35.2 136.4 19.2 L136.4 -16.8z M136.4 -22 L28 -22 L28 0 L136.4 0z M134.4 -134.8 L134.4 -153.6 L120.8 -153.6 L17.6 -20 L17.6 0 L31.6 0z M122.4 -153.6 L16 -153.6 L16 -131.6 L122.4 -131.6z" transform="translate(-16 281.6)"/></svg>
</div><!--END-SVGS don't remove this comment-->
- <div class="row intro"><div>
- <h2 class="back"><a href="../">The Inter UI font family</a></h2>
- <h1><a href="./">Inter UI glyphs</a></h1>
- <p>
- This shows the complete set of glyphs in Inter UI Regular.
- You can zoom in and out by pressing
- <kbd>⌘</kbd><kbd>+</kbd> and
- <kbd>⌘</kbd><kbd>−</kbd> on your keyboard.
- Click on a glyph to see more details about it.
- </p>
- </div></div>
+<div class="row intro"><div>
+ <h1><a href="./">Glyphs</a></h1>
+ <p>
+ This shows the complete set of glyphs in Inter UI Regular.
+ You can zoom in and out by pressing
+ <kbd>⌘</kbd><kbd>+</kbd> and
+ <kbd>⌘</kbd><kbd>−</kbd> on your keyboard.
+ Click on a glyph to see more details about it.
+ </p>
+</div></div>
- <div id="glyphs">
- <div id="single-info" style="display:none">
- <ul>
- <li>Glyph name: <span class="name"></span></li>
- <li class="unicode">Unicode: <a><span class="unicodeCodePoint num"></span> <span class="unicodeName"></span></a></li>
- <li>Advance width: <span class="advanceWidth num"></span></li>
- <li>Left margin: <span class="marginLeft num"></span></li>
- <li>Right margin: <span class="marginRight num"></span></li>
- <li>Color mark: <span class="colorMark">&nbsp;</span></li>
- <li><a class="svgFile">&darr; Download SVG file</a></li>
- </ul>
- </div>
- </div>
+<div id="glyphs">
+ <div id="single-info" style="display:none">
+ <ul>
+ <li>Glyph name: <span class="name"></span></li>
+ <li class="unicode">Unicode: <a><span class="unicodeCodePoint num"></span> <span class="unicodeName"></span></a></li>
+ <li>Advance width: <span class="advanceWidth num"></span></li>
+ <li>Left margin: <span class="marginLeft num"></span></li>
+ <li>Right margin: <span class="marginRight num"></span></li>
+ <li>Color mark: <span class="colorMark">&nbsp;</span></li>
+ <li><a class="svgFile">&darr; Download SVG file</a></li>
+ </ul>
+ </div>
+</div>
- <div class="row kerning"><div>
- <h2 id="kerning"><a href="#kerning">Kerning</a></h2>
- <div id="kerning-list"></div>
- </div></div>
+<div class="row kerning"><div>
+ <h2 id="kerning"><a href="#kerning">Kerning</a></h2>
+ <div id="kerning-list"></div>
+</div></div>
- <script src="glyphs.js"></script>
- </body>
-</html>
+<script src="glyphs.js?v={{ glyphs_js_v }}"></script>
diff --git a/docs/index.html b/docs/index.html
index 4aadee974..fb2345fc9 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,360 +1,326 @@
-<!DOCTYPE HTML>
-<html lang="en" prefix="og: http://ogp.me/ns#">
- <head>
- <meta charset="utf-8">
- <title>Inter UI font family</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta property="og:title" content="Inter UI font family">
- <meta property="twitter:title" content="Inter UI font family">
- <meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:card" content="summary">
- <meta property="twitter:site" content="@rsms">
- <meta property="twitter:creator" content="@rsms">
- <meta property="og:image" content="https://rsms.me/inter/res/poster.png">
- <meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
- <meta property="fb:app_id" content="38027689216">
- <meta property="og:url" content="https://rsms.me/inter/">
- <meta property="og:site_name" content="rsms.me">
- <meta property="og:type" content="product">
- <meta property="og:locale" content="en_US" />
- <meta name="format-detection" content="telephone=no">
- <link rel="icon" type="image/png" href="favicon.png" />
- <link href="inter-ui.css?v=2.5" rel="stylesheet">
- <link href="index.css?v=5" rel="stylesheet">
- </head>
- <body>
-
- <div class="row menu">
- <ul class="menu">
- <li class="home"><a href="../">Inter UI</a></li>
- <li><a class="download-link"
- href="https://github.com/rsms/inter/releases/latest/"
- >Download</a></li>
- <li><a href="samples/">Samples</a></li>
- <li><a href="lab/">Playground</a></li>
- <li><a href="https://github.com/rsms/inter/">Source</a></li>
- </ul>
- </div>
-
- <div class="row"><div>
- <h1>The Inter UI font family</h1>
- <p>
- Inter UI is a typeface specially designed for user interfaces
- with focus on high legibility of small-to-medium sized text on computer screens.
- </p>
- <p>
- The family features a tall x-height to aid in readability of mixed-case and
- lower-case text. Several OpenType features are provided as well,
- like contextual alternates that adjusts punctuation depending on the shape of
- surrounding glyphs, slashed zero for when you need to disambiguate "0" from "o",
- tabular numbers, etc.
- </p>
- </div></div>
-
- <div class="row white" style="padding-bottom:0"><div>
- <p id="samples" class="samples items">
- <a href="samples/" class="plain"><img src="samples/img/01.png" srcset="samples/img/01@2x.png 2x" width="888"></a>
- </p>
- <p style="text-align:center">
- <a href="samples/" class="plain">More samples -></a>
- <br><br>
- </p>
- </div></div>
-
- <div class="row dark"><div>
-
- <h2><a id="usage" href="#usage">How do I use it?</a></h2>
- <p>
- Using the font is as easy as
- <a class="download-link" href="https://github.com/rsms/inter/releases/latest/">download &amp; installing</a> locally on your computer.
- </p>
- <p>
- You're free to bundle copies of Inter UI with your software, even if it's
- commercial and you charge money for your software. Inter UI can also be used
- on the web by either hosting the font files yourself or by including this CSS:
- </p>
- <code>@import url('https://rsms.me/inter/inter-ui.css');</code>
- <p>Use the following CSS rules to specify the Inter UI family:</p>
- <code>font-family: 'Inter UI', sans-serif;</code>
-
- <p>&nbsp;</p>
-
- <h2><a id="free" href="#free">How much does it cost?</a></h2>
- <p>
- Inter UI is a <a href="https://github.com/rsms/inter">free and open source</a> font family. You are free to use this font in almost any way imaginable.
- Refer to the <a href="https://choosealicense.com/licenses/ofl-1.1/">SIL Open Font License 1.1</a> for exact details on what the conditions and restrictions are.
- </p>
-
- </div></div>
-
- <div class="row"><div>
- <p>
- There are currently four <a id="weights" href="#weights">weights</a>
- </p>
- <img src="res/weights-and-styles.svg" style="opacity:0.76;width:100%;display:block;margin:2em 0 3em 0">
- <h2><a id="features" href="#features">Features</a></h2>
- <boxes>
- <box>
- <h3>Contextual alternates (<q title='OpenType feature ID'>calt</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r><in>12<em>:</em>34, FE<em>—</em>X</in><to></to><out>12:34, FE—X</out></r>
- <r><in>4<em>.</em>2</in><to></to><out>4.2</out></r>
- <r><in>SFO <em>-></em> STO</in><to></to><out>SFO -> STO</out></r>
- <r><in>IIA <em>—></em> OGG</in><to></to><out>IIA —> OGG</out></r>
- <r><in>M<em>@</em>N m@n</in><to></to><out>M@N m@n</out></r>
- </t></tablex>
- </box>
-
- <box>
- <h3>Tabular numbers (<q title='OpenType feature ID'>tnum</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r><in><em>1</em>23456<em>7</em>890</in><to></to><out class="tnum">1234567890</out></r>
- <r><in>1131711<em>&nbsp;</em></in><to></to><out class="tnum">1131711<em>&nbsp;</em></out></r>
- <r><in>0040900<em>&nbsp;</em></in><to></to><out class="tnum">0040900<em>&nbsp;</em></out></r>
- <r><in>11:31,711<em>&nbsp;</em></in><to></to><out class="tnum">11:31,711<em>&nbsp;</em></out></r>
- <r><in>00:40.900<em>&nbsp;</em></in><to></to><out class="tnum">00:40.900<em>&nbsp;</em></out></r>
- </t></tablex>
- </box>
-
- <box>
- <h3>Slashed zero (<q title='OpenType feature ID'>zero</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r><in><em>0</em>123</in><to></to><out class="zero">0123</out></r>
- </t></tablex>
- </box>
-
- <box>
- <h3>Fractions (<q title='OpenType feature ID'>frac</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r>
- <in><em>1/3</em> <em>22/9</em> <em>3/4/5</em></in>
- <to></to><out class="frac">1/3 22/9 3/4/5</out>
- </r>
- </t></tablex>
- </box>
-
- <box>
- <h3>Stylistic set 1: Alternate digits (<q title='OpenType feature ID'>ss01</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r>
- <in><em>1</em>23<em>4</em>5<em>6</em>78<em>9</em>0</in>
- <to></to><out class="ss01">1234567890</out>
- </r>
- <r><in><em>1</em></in><to></to><out class="ss01">1</out></r>
- <r><in><em>4</em></in><to></to><out class="ss01">4</out></r>
- <r><in><em>6</em></in><to></to><out class="ss01">6</out></r>
- <r><in><em>9</em></in><to></to><out class="ss01">9</out></r>
- </t></tablex>
- </box>
-
- <box>
- <h3>Case alternates (<q title='OpenType feature ID'>case</q>)</h3>
- <tablex><t>
- <h><in>Disabled</in><to></to><out>Enabled</out></h>
- <r>
- <in><em>(</em>Hello<em>)</em> <em>[</em>World<em>]</em> <em>{</em>9000<em>}</em></in>
- <to></to><out class="case">(Hello) [World] {9000}</out>
- </r>
- <r><in>SCHOOL <em>@</em> RUN</in><to></to><out class="case">SCHOOL @ RUN</out></r>
- <r><in>3 <em>+</em> 9 <em>=</em> 12 <em>*</em> 1</in><to></to><out class="case">3 + 9 = 12 * 1</out></r>
- <r><in><em>*</em> <em>+</em> <em>÷</em> <em>±</em> <em>×</em> <em>=</em> <em>≠</em> <em>•</em></in><to></to><out class="case">* + ÷ ± × = ≠ •</out></r>
- <r><in><em>→</em> <em>←</em> <em>⟶</em> <em>⟵</em> <em>−</em> <em>-</em> <em>–</em> <em>—</em> <em>:</em></in><to></to><out class="case">→ ← ⟶ ⟵ − - – — :</out></r>
- </t></tablex>
- </box>
-
- </boxes>
-
- <p>
- Also includes some
- Localized Forms (<q title='OpenType feature ID'>locl</q>),
- Numerators (<q title='OpenType feature ID'>numr</q>) and
- Denominators (<q title='OpenType feature ID'>dnom</q>).
- </p>
-
- <p>&nbsp;</p>
-
- <h2 class="banner"><a href="glyphs/">Browse all glyphs -></a></h2>
- </div></div>
-
- <div class="row-divider"></div>
-
- <div class="row"><div>
- <h2><a id="story" href="#story">The story behind Inter UI</a></h2>
- <p>
- Inter UI started out in late 2016 as an experiment to build a perfectly
- pixel-fitting font at a specific small size (11px.) The idea was that
- by crafting a font in a particular way, with a particular coordinate system
- (Units Per EM), and for a particular target rasterization size (11), it would
- be possible to get the best of both sharpness and readability.
- </p>
- <p>
- However after a few months of using an early version of Inter UI, it dawned
- on everyone exposed to the test that this approach had some serious real-world
- problems. Most notably that it was really hard to read longer text. Because of
- the pixel-aligning nature of that approach, the font took an almost
- <a href="https://www.figma.com/file/HPqDViSCB8fAWuxaV2ousFMv">mono-spaced appearance</a>,
- making it really easy to read numbers, punctuation and very short
- words, but eye-straining to read anything longer.
- </p>
- <p>
- The project was rebooted with a different approach, sticking with the
- specific UPM, but crafting glyphs and kerning in a way that made for
- more variation in the rhythm and smoother vertical and horizontal stems.
- As Inter UI was being developed, it was tested on an internal version of
- <a href="https://www.figma.com/">Figma</a>—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback.
- </p>
-
- <p>&nbsp;</p>
-
- <h2><a id="status" href="#status">Current status &amp; usability</a></h2>
- <p>
- Inter UI works great for English-language text, and pretty well for other
- Latin and Cyrillic languages. There's still a lot of work to be done, and
- <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">contributions are warmly welcomed</a>. The playground contains <a href="lab/?sample=Body%20text%201&size=16">a lot of samples</a>, including some common <a href="lab/?sample=Kerning%20body%20multi-lang&size=16">non English-language words in the playground.</a>
- </p>
-
- <p>
- Please refer to the <a href="glyphs/">glyph repertoire</a>
- for an overview of currently-available glyphs and their quality.
- </p>
-
- <p>&nbsp;</p>
-
- <h2><a id="faq" href="#faq">FAQ</a></h2>
- <ul class="faq">
-
- <li class="q" id="faq-using-features">
- How do I enable and disable font features?
- </li>
- <li class="a">
- In web browsers you'll want to use
- <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings"><q>font-feature-settings</q></a>.
- In Figma you can access features via the
- <a href="https://help.figma.com/text/opentype-features">Advanced Typography panel.</a>
- In Illustrator, Photoshop and friends, you can access features via the
- <a href="https://helpx.adobe.com/illustrator/using/special-characters.html#opentype_panel_overview">Characters and OpenType panels.</a>
- Sketch doesn't provide a UI for configuring font features, but there's
- <a href="https://sketchtalk.io/discussion/comment/1478/#Comment_1478">a workaround using macOS's native font UI.</a>
- </li>
-
- <li class="q" id="faq-unhinted-vs-hinted">
- What is the difference between "unhinted" and "hinted" font files?
- </li>
- <li class="a">
- The font files in the "hinted" folders have additional data in them
- for assisting
- <a href="https://en.wikipedia.org/wiki/ClearType">ClearType</a>,
- the text rasterizer used by Microsoft Windows (and some Linux distributions.)
- You want to use the "hinted" fonts only if you are targeting Windows users
- <em>and</em> prefer the different look of these "hinted" fonts.
- Additionally, hinting data makes the font files larger, so if you are
- using Inter UI on websites, the extra size of these files is another
- consideration to make.
- <a href="https://www.typotheque.com/articles/hinting">
- This article explains hinting at a greater length.</a>
- </li>
-
-
- <li class="q" id="faq-cdn">
- How reliable are the fonts served from rsms.me/inter? Is it on a CDN?
- </li>
- <li class="a">
- rsms.me/inter is backed by GitHub's server network and distributed
- globally on the CloudFlare CDN, making usage of
- <q>https://rsms.me/inter/inter-ui.css</q> and associated font
- files very reliable and fast throughout the world.
- </li>
-
- <li class="q" id="faq-contribute">
- Can I help with improving Inter UI?
- </li>
- <li class="a">
- Yes you can! Inter UI is an open-source project, meaning the source
- code—or "source design" if you will—that is used to build the font files
- <a href="https://github.com/rsms/inter">are freely available</a> to improve upon.
- Font making requires a fair bit of technical work and
- depending on what you'd like to do, some things might be more fun
- depending on your technical skills.
- The <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">"Contributing" document</a> is a great place to start. The document outlines where
- you can have the biggest impact, how things are setup and how to get
- started.
- </li>
-
- <li class="q" id="faq-start-date">
- This website claims work started in 2016, but the git repository's log says it started later?
- </li>
- <li class="a">
- Inter UI was developed in an a private, internal git repository
- starting in November 2016, prior to being published on August 22, 2017.
- Between November 2016 and August 2017, there were
- <num>2&#x2006;990&#x2006;150</num> line edits made across 247 versions.
- The reason the public GitHub repository does not reflect this is the
- fact that the project was initially only internal at the company where
- the author works and had some sensitive information "checked in",
- like AWS server details and internal author identity in
- all commit messages. Maybe one day we can write an elaborate git
- filter-branch program and convert the filter the old repository to make
- it public, but what would be the point of that?&nbsp; :—)
- </li>
-
- <li class="q" id="faq-contact">
- I've made a cool thing that uses Inter UI, can I share it with you?
- &nbsp;<dem>or</dem>
- </li>
- <li class="q">
- I have a different question
- </li>
- <li class="a">
- Reach out on <a href="https://twitter.com/rsms">Twitter (@rsms)</a> or over <a href="mailto:rasmus@notion.se">email</a>
- </li>
-
-
- </ul>
-
- </div></div>
-
-
- <div class="row"><div>
- — <a href="https://twitter.com/rsms" class="plain">@rsms</a>
- </div></div>
-
- <script src="index.js?v=2"></script>
- <script>
- (function(){
-
- // FAQ anchors
- var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn
- for (i = 0; i < av.length; ++i) {
- e = av[i]
- tn = document.createTextNode('Q  ')
- e.insertBefore(tn, e.firstChild)
- id = e.id
- if (id) {
- a = document.createElement('a')
- // a.id = id
- a.href = '#' + id
- a.className = 'plain'
- a.innerHTML = e.innerHTML
- e.innerText = ''
- e.appendChild(a)
- }
- }
- av = document.querySelectorAll('ul.faq > li.a')
- for (i = 0; i < av.length; ++i) {
- e = av[i]
- tn = document.createTextNode('A  ')
- e.insertBefore(tn, e.firstChild)
- }
-
- })();
- </script>
- </body>
-</html>
+---
+layout: default
+---
+
+<div class="row"><div>
+ <h1>The Inter UI font family</h1>
+ <p>
+ Inter UI is a typeface specially designed for user interfaces
+ with focus on high legibility of small-to-medium sized text on computer screens.
+ </p>
+ <p>
+ The family features a tall x-height to aid in readability of mixed-case and
+ lower-case text. Several OpenType features are provided as well,
+ like contextual alternates that adjusts punctuation depending on the shape of
+ surrounding glyphs, slashed zero for when you need to disambiguate "0" from "o",
+ tabular numbers, etc.
+ </p>
+</div></div>
+
+<div class="row white" style="padding-bottom:0"><div>
+ <p id="samples" class="samples items sample-images">
+ <a href="samples/" class="plain"><img src="samples/img/01.png" srcset="samples/img/01@2x.png 2x" width="888"></a>
+ </p>
+ <p style="text-align:center">
+ <a href="samples/" class="plain">More samples -></a>
+ <br><br>
+ </p>
+</div></div>
+
+<div class="row dark"><div>
+
+ <h2><a id="usage" href="#usage">How do I use it?</a></h2>
+ <p>
+ Using the font is as easy as
+ <a class="download-link" href="https://github.com/rsms/inter/releases/latest/">download &amp; installing</a> locally on your computer.
+ </p>
+ <p>
+ You're free to bundle copies of Inter UI with your software, even if it's
+ commercial and you charge money for your software. Inter UI can also be used
+ on the web by either hosting the font files yourself or by including this CSS:
+ </p>
+ <code>@import url('https://rsms.me/inter/inter-ui.css');</code>
+ <p>Use the following CSS rules to specify the Inter UI family:</p>
+ <code>font-family: 'Inter UI', sans-serif;</code>
+
+ <p>&nbsp;</p>
+
+ <h2><a href="{{url_root}}dynmetrics/">Dynamic Metrics</a></h2>
+ <p>
+ There's of course no absolute right or wrong when it comes to expressing yourself with typography, but Inter UI <em>Dynamic Metrics</em> provides guidelines for good typography. You simply provide the optical font size, and the tracking and leading is calculated for you to produce the best results.
+ <a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics —></a>
+ </p>
+
+ <p>&nbsp;</p>
+
+ <h2><a id="free" href="#free">How much does it cost?</a></h2>
+ <p>
+ Inter UI is a <a href="https://github.com/rsms/inter">free and open source</a> font family. You are free to use this font in almost any way imaginable.
+ Refer to the <a href="https://choosealicense.com/licenses/ofl-1.1/">SIL Open Font License 1.1</a> for exact details on what the conditions and restrictions are.
+ </p>
+
+</div></div>
+
+<div class="row"><div>
+ <p>
+ There are currently four <a id="weights" href="#weights">weights</a>
+ </p>
+ <img src="res/weights-and-styles.svg" style="opacity:0.76;width:100%;display:block;margin:2em 0 3em 0">
+ <h2><a id="features" href="#features">Features</a></h2>
+ <boxes>
+ <box>
+ <h3>Contextual alternates (<q title='OpenType feature ID'>calt</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r><in>12<em>:</em>34, FE<em>—</em>X</in><to></to><out>12:34, FE—X</out></r>
+ <r><in>4<em>.</em>2</in><to></to><out>4.2</out></r>
+ <r><in>SFO <em>-></em> STO</in><to></to><out>SFO -> STO</out></r>
+ <r><in>IIA <em>—></em> OGG</in><to></to><out>IIA —> OGG</out></r>
+ <r><in>M<em>@</em>N m@n</in><to></to><out>M@N m@n</out></r>
+ </t></tablex>
+ </box>
+
+ <box>
+ <h3>Tabular numbers (<q title='OpenType feature ID'>tnum</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r><in><em>1</em>23456<em>7</em>890</in><to></to><out class="tnum">1234567890</out></r>
+ <r><in>1131711<em>&nbsp;</em></in><to></to><out class="tnum">1131711<em>&nbsp;</em></out></r>
+ <r><in>0040900<em>&nbsp;</em></in><to></to><out class="tnum">0040900<em>&nbsp;</em></out></r>
+ <r><in>11:31,711<em>&nbsp;</em></in><to></to><out class="tnum">11:31,711<em>&nbsp;</em></out></r>
+ <r><in>00:40.900<em>&nbsp;</em></in><to></to><out class="tnum">00:40.900<em>&nbsp;</em></out></r>
+ </t></tablex>
+ </box>
+
+ <box>
+ <h3>Slashed zero (<q title='OpenType feature ID'>zero</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r><in><em>0</em>123</in><to></to><out class="zero">0123</out></r>
+ </t></tablex>
+ </box>
+
+ <box>
+ <h3>Fractions (<q title='OpenType feature ID'>frac</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r>
+ <in><em>1/3</em> <em>22/9</em> <em>3/4/5</em></in>
+ <to></to><out class="frac">1/3 22/9 3/4/5</out>
+ </r>
+ </t></tablex>
+ </box>
+
+ <box>
+ <h3>Stylistic set 1: Alternate digits (<q title='OpenType feature ID'>ss01</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r>
+ <in><em>1</em>23<em>4</em>5<em>6</em>78<em>9</em>0</in>
+ <to></to><out class="ss01">1234567890</out>
+ </r>
+ <r><in><em>1</em></in><to></to><out class="ss01">1</out></r>
+ <r><in><em>4</em></in><to></to><out class="ss01">4</out></r>
+ <r><in><em>6</em></in><to></to><out class="ss01">6</out></r>
+ <r><in><em>9</em></in><to></to><out class="ss01">9</out></r>
+ </t></tablex>
+ </box>
+
+ <box>
+ <h3>Case alternates (<q title='OpenType feature ID'>case</q>)</h3>
+ <tablex><t>
+ <h><in>Disabled</in><to></to><out>Enabled</out></h>
+ <r>
+ <in><em>(</em>Hello<em>)</em> <em>[</em>World<em>]</em> <em>{</em>9000<em>}</em></in>
+ <to></to><out class="case">(Hello) [World] {9000}</out>
+ </r>
+ <r><in>SCHOOL <em>@</em> RUN</in><to></to><out class="case">SCHOOL @ RUN</out></r>
+ <r><in>3 <em>+</em> 9 <em>=</em> 12 <em>*</em> 1</in><to></to><out class="case">3 + 9 = 12 * 1</out></r>
+ <r><in><em>*</em> <em>+</em> <em>÷</em> <em>±</em> <em>×</em> <em>=</em> <em>≠</em> <em>•</em></in><to></to><out class="case">* + ÷ ± × = ≠ •</out></r>
+ <r><in><em>→</em> <em>←</em> <em>⟶</em> <em>⟵</em> <em>−</em> <em>-</em> <em>–</em> <em>—</em> <em>:</em></in><to></to><out class="case">→ ← ⟶ ⟵ − - – — :</out></r>
+ </t></tablex>
+ </box>
+
+ </boxes>
+
+ <p>
+ Also includes some
+ Localized Forms (<q title='OpenType feature ID'>locl</q>),
+ Numerators (<q title='OpenType feature ID'>numr</q>) and
+ Denominators (<q title='OpenType feature ID'>dnom</q>).
+ </p>
+
+ <p>&nbsp;</p>
+
+ <h2 class="banner"><a href="glyphs/">Browse all glyphs -></a></h2>
+</div></div>
+
+<div class="row-divider"></div>
+
+<div class="row"><div>
+ <h2><a id="story" href="#story">The story behind Inter UI</a></h2>
+ <p>
+ Inter UI started out in late 2016 as an experiment to build a perfectly
+ pixel-fitting font at a specific small size (11px.) The idea was that
+ by crafting a font in a particular way, with a particular coordinate system
+ (Units Per EM), and for a particular target rasterization size (11), it would
+ be possible to get the best of both sharpness and readability.
+ </p>
+ <p>
+ However after a few months of using an early version of Inter UI, it dawned
+ on everyone exposed to the test that this approach had some serious real-world
+ problems. Most notably that it was really hard to read longer text. Because of
+ the pixel-aligning nature of that approach, the font took an almost
+ <a href="https://www.figma.com/file/HPqDViSCB8fAWuxaV2ousFMv">mono-spaced appearance</a>,
+ making it really easy to read numbers, punctuation and very short
+ words, but eye-straining to read anything longer.
+ </p>
+ <p>
+ The project was rebooted with a different approach, sticking with the
+ specific UPM, but crafting glyphs and kerning in a way that made for
+ more variation in the rhythm and smoother vertical and horizontal stems.
+ As Inter UI was being developed, it was tested on an internal version of
+ <a href="https://www.figma.com/">Figma</a>—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback.
+ </p>
+
+ <p>&nbsp;</p>
+
+ <h2><a id="status" href="#status">Current status &amp; usability</a></h2>
+ <p>
+ Inter UI works great for English-language text, and pretty well for other
+ Latin and Cyrillic languages. There's still a lot of work to be done, and
+ <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">contributions are warmly welcomed</a>. The playground contains <a href="lab/?sample=Body%20text%201&size=16">a lot of samples</a>, including some common <a href="lab/?sample=Kerning%20body%20multi-lang&size=16">non English-language words in the playground.</a>
+ </p>
+
+ <p>
+ Please refer to the <a href="glyphs/">glyph repertoire</a>
+ for an overview of currently-available glyphs and their quality.
+ </p>
+
+ <p>&nbsp;</p>
+
+ <h2><a id="faq" href="#faq">FAQ</a></h2>
+ <ul class="faq">
+
+ <li class="q" id="faq-using-features">
+ How do I enable and disable font features?
+ </li>
+ <li class="a">
+ In web browsers you'll want to use
+ <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-feature-settings"><q>font-feature-settings</q></a>.
+ In Figma you can access features via the
+ <a href="https://help.figma.com/text/opentype-features">Advanced Typography panel.</a>
+ In Illustrator, Photoshop and friends, you can access features via the
+ <a href="https://helpx.adobe.com/illustrator/using/special-characters.html#opentype_panel_overview">Characters and OpenType panels.</a>
+ Sketch doesn't provide a UI for configuring font features, but there's
+ <a href="https://sketchtalk.io/discussion/comment/1478/#Comment_1478">a workaround using macOS's native font UI.</a>
+ </li>
+
+ <li class="q" id="faq-unhinted-vs-hinted">
+ What is the difference between "unhinted" and "hinted" font files?
+ </li>
+ <li class="a">
+ The font files in the "hinted" folders have additional data in them
+ for assisting
+ <a href="https://en.wikipedia.org/wiki/ClearType">ClearType</a>,
+ the text rasterizer used by Microsoft Windows (and some Linux distributions.)
+ You want to use the "hinted" fonts only if you are targeting Windows users
+ <em>and</em> prefer the different look of these "hinted" fonts.
+ Additionally, hinting data makes the font files larger, so if you are
+ using Inter UI on websites, the extra size of these files is another
+ consideration to make.
+ <a href="https://www.typotheque.com/articles/hinting">
+ This article explains hinting at a greater length.</a>
+ </li>
+
+
+ <li class="q" id="faq-cdn">
+ How reliable are the fonts served from rsms.me/inter? Is it on a CDN?
+ </li>
+ <li class="a">
+ rsms.me/inter is backed by GitHub's server network and distributed
+ globally on the CloudFlare CDN, making usage of
+ <q>https://rsms.me/inter/inter-ui.css</q> and associated font
+ files very reliable and fast throughout the world.
+ </li>
+
+ <li class="q" id="faq-contribute">
+ Can I help with improving Inter UI?
+ </li>
+ <li class="a">
+ Yes you can! Inter UI is an open-source project, meaning the source
+ code—or "source design" if you will—that is used to build the font files
+ <a href="https://github.com/rsms/inter">are freely available</a> to improve upon.
+ Font making requires a fair bit of technical work and
+ depending on what you'd like to do, some things might be more fun
+ depending on your technical skills.
+ The <a href="https://github.com/rsms/inter/blob/master/CONTRIBUTING.md">"Contributing" document</a> is a great place to start. The document outlines where
+ you can have the biggest impact, how things are setup and how to get
+ started.
+ </li>
+
+ <li class="q" id="faq-start-date">
+ This website claims work started in 2016, but the git repository's log says it started later?
+ </li>
+ <li class="a">
+ Inter UI was developed in an a private, internal git repository
+ starting in November 2016, prior to being published on August 22, 2017.
+ Between November 2016 and August 2017, there were
+ <num>2&#x2006;990&#x2006;150</num> line edits made across 247 versions.
+ The reason the public GitHub repository does not reflect this is the
+ fact that the project was initially only internal at the company where
+ the author works and had some sensitive information "checked in",
+ like AWS server details and internal author identity in
+ all commit messages. Maybe one day we can write an elaborate git
+ filter-branch program and convert the filter the old repository to make
+ it public, but what would be the point of that?&nbsp; :—)
+ </li>
+
+ <li class="q" id="faq-contact">
+ I've made a cool thing that uses Inter UI, can I share it with you?
+ &nbsp;<dem>or</dem>
+ </li>
+ <li class="q">
+ I have a different question
+ </li>
+ <li class="a">
+ Reach out on <a href="https://twitter.com/rsms">Twitter (@rsms)</a> or over <a href="mailto:rasmus@notion.se">email</a>
+ </li>
+
+
+ </ul>
+
+</div></div>
+
+
+<div class="row"><div>
+ — <a href="https://twitter.com/rsms" class="plain">@rsms</a>
+</div></div>
+
+<script>(function(){
+
+ // FAQ anchors
+ var av = document.querySelectorAll('ul.faq > li.q'), a, i, e, id, tn
+ for (i = 0; i < av.length; ++i) {
+ e = av[i]
+ tn = document.createTextNode('Q  ')
+ e.insertBefore(tn, e.firstChild)
+ id = e.id
+ if (id) {
+ a = document.createElement('a')
+ // a.id = id
+ a.href = '#' + id
+ a.className = 'plain'
+ a.innerHTML = e.innerHTML
+ e.innerText = ''
+ e.appendChild(a)
+ }
+ }
+ av = document.querySelectorAll('ul.faq > li.a')
+ for (i = 0; i < av.length; ++i) {
+ e = av[i]
+ tn = document.createTextNode('A  ')
+ e.insertBefore(tn, e.firstChild)
+ }
+
+})();</script>
diff --git a/docs/index.js b/docs/index.js
deleted file mode 100644
index f7773c537..000000000
--- a/docs/index.js
+++ /dev/null
@@ -1,138 +0,0 @@
-var isMac = false
-
-function $$(query, el) {
- return [].slice.call((el || document).querySelectorAll(query))
-}
-
-function $(query, el) {
- return (el || document).querySelector(query)
-}
-
-// fetchjson(url string, cb (err Error, d Object)->nil)
-//
-var fetchjson = (
- typeof window.fetch == 'function' ? (
- function _fetchjson(url, cb) {
- return window.fetch(url)
- .then(function(r) { return r.json() })
- .then(function(data) { cb(null, data) })
- .catch(cb)
- }
- ) :
- function _fetchjson(url, cb) {
- var r = new XMLHttpRequest()
- r.addEventListener("load", function(){
- try {
- cb(null, JSON.parse(r.responseText))
- } catch (err) {
- cb(err)
- }
- })
- r.open("GET", url)
- r.send()
- }
-)
-
-;(function(){
-"use strict";
-
-
-// anim.min.js
-var anim=function(h){h=function(a,e,f,b){var g,d,c=[],j=function(a){
-if(a=c.shift())a[1]?h.apply(this,a).anim(j):0<a[0]?setTimeout(j,1E3*a[0]):(a[0](),j())};
-a.charAt&&(a=document.getElementById(a));if(0<a||!a)e={},f=0,j(c=[[a||0]]);
-q(e,{padding:0,margin:0,border:"Width"},[l,m,n,p]);q(e,{borderRadius:"Radius"},[l+p,l+m,n+m,n+p]);++r;
-for(g in e)d=e[g],!d.to&&0!==d.to&&(d=e[g]={to:d}),h.defs(d,a,g,b);h.iter(e,1E3*f,j);
-return{anim:function(){c.push([].slice.call(arguments));return this}}};
-var l="Top", m="Right",n="Bottom",p="Left",r=1,q=function(a,e,f,b,g,d,c){for(b in a)if(b in e){c=a[b];
-for(g=0;d=f[g];g++)a[b.replace(e[b],"")+d+(e[b]||"")]={to:0===c.to?c.to:c.to||c,fr:c.fr,e:c.e};
-delete a[b]}},s=function(w,a){return w["r"+a]||w["webkitR"+a]||w["mozR"+a]||w["msR"+a]||w["oR"+a]}(
-window,"equestAnimationFrame");h.defs=function(a,e,f,b,g){g=e.style;a.a=f;a.n=e;a.s=f in g?g:e;
-a.e=a.e||b;a.fr=a.fr||(0===a.fr?0:a.s==e?e[f]:(window.getComputedStyle?getComputedStyle(e, null)
-:e.currentStyle)[f]);a.u=(/\d(\D+)$/.exec(a.to)||/\d(\D+)$/.exec(a.fr)||[0,0])[1];a.fn=/color/i.test(f)?
-h.fx.color:h.fx[f]||h.fx._;a.mx="anim_"+f;e[a.mx]=a.mxv=r;e[a.mx]!=a.mxv&&(a.mxv=null)};h.iter=function(a,e,f){
-var b,g,d,c,h,k=+new Date+e;b=function(){g=k-(new Date).getTime();if(50>g){
-for(d in a)d=a[d],d.p=1,d.fn(d,d.n,d.to,d.fr,d.a,d.e);f&&f()}else{g/=e;for(d in a){d=a[d];
-if(d.n[d.mx]!=d.mxv)return;h=d.e;c=g;"lin"==h?c=1-c:"ease"==h?(c=2*(0.5-c),c=1-(c*c*c-3*c+2)/4):
-"ease-in"==h?(c= 1-c,c*=c*c):c=1-c*c*c;d.p=c;d.fn(d,d.n,d.to,d.fr,d.a,d.e)}s?s(b):setTimeout(b,20)}};
-b()};h.fx={_:function(a,e,f,b,g){b=parseFloat(b)||0;f=parseFloat(f)||0;a.s[g]=(1<=a.p?f:a.p*(f-b)+b)+a.u},
-width:function(a,e,f,b,g,d){0<=a._fr||(a._fr=!isNaN(b=parseFloat(b))?b:"width"==g?e.clientWidth:e.clientHeight);
-h.fx._(a,e,f,a._fr,g,d)},opacity:function(a,e,f,b,g){if(isNaN(b=b||a._fr))b=e.style,b.zoom=1,
-b=a._fr=(/alpha\(opacity=(\d+)\b/i.exec(b.filter)||{})[1]/100||1;b*=1;f=a.p*(f-b)+b;e=e.style;g in e?e[g]= f:
-e.filter=1<=f?"":"alpha("+g+"="+Math.round(100*f)+")"},color:function(a,e,f,b,g,d,c,j){
-a.ok||(f=a.to=h.toRGBA(f),b=a.fr=h.toRGBA(b),0==f[3]&&(f=[].concat(b),f[3]=0),0==b[3]&&
-(b=[].concat(f),b[3]=0),a.ok=1);j=[0,0,0,a.p*(f[3]-b[3])+1*b[3]];for(c=2;0<=c;c--)j[c]=Math.round(
-a.p*(f[c]-b[c])+1*b[c]);(1<=j[3]||h.rgbaIE)&&j.pop();try{a.s[g]=(3<j.length?"rgba(":"rgb(")+j.join(",")+")"
-}catch(k){h.rgbaIE=1}}};h.fx.height=h.fx.width;
-h.RGBA=/#(.)(.)(.)\b|#(..)(..)(..)\b|(\d+)%,(\d+)%,(\d+)%(?:,([\d\.]+))?|(\d+),(\d+),(\d+)(?:,([\d\.]+))?\b/;
-h.toRGBA=function(a,e){e=[0,0,0,0];a.replace(/\s/g,"").replace(h.RGBA,function(a,b,g,d,c,h,k,l,m,n,p,q,r,s,t){
-k=[b+b||c,g+g||h,d+d||k];b=[l,m,n];for(a=0;3>a;a++)k[a]=parseInt(k[a],16),b[a]=Math.round(2.55*b[a]);
-e=[k[0]||b[0]||q||0,k[1]||b[1]||r||0,k[2]||b[2]||s||0,p||t||1]});return e};return h}();
-
-
-if (!window.MSStream &&
- /mac|ipad|iphone|ipod/i.test(navigator.userAgent))
-{
- isMac = true
- document.body.classList.add('mac_or_ios')
- if (navigator.userAgent.indexOf('Safari') != -1) {
- document.body.classList.add('safari')
- }
-}
-
-
-// timeNow() :float
-var timeNow = (
- window.performance !== undefined && window.performance.now ? function() {
- return window.performance.now()
- } : Date.now ? function() {
- return Date.now()
- } : function() {
- return (new Date()).getTime()
- }
-)
-
-
-// download-link
-fetchjson('/inter/info.json', function(err, data) {
- if (err) { throw err }
- var ids = Object.keys(data)
- var regularId = ids[0]
- ids.forEach(function(id){
- if (id.indexOf('Inter UI Regular:') == 0) {
- regularId = id
- }
- })
- if (ids.length == 0) {
- console.error('failed to find Inter UI Regular in info.json', data)
- return
- }
- var regular = data[regularId]
- // console.log('info.json:', regular)
- if (regular.names && regular.names.version) {
- var v = regular.names.version
- var p = v.indexOf(';')
- if (p != -1) {
- v = v.substr(0, p)
- }
- var directDownloadURL =
- 'https://github.com/rsms/inter/releases/download/v' + v +
- '/Inter-UI-' + v + '.zip'
- var av = document.querySelectorAll('a.download-link'), i, e
- for (i = 0; i < av.length; ++i) {
- e = av[i]
- e.href = directDownloadURL
- }
- }
-})
-
-
-// Google Analytics
-;(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-ga('create', 'UA-105091131-2', 'auto');
-ga('send', 'pageview');
-
-})();
diff --git a/docs/index.css b/docs/res/base.css
index 874725192..5cc6cc39d 100644
--- a/docs/index.css
+++ b/docs/res/base.css
@@ -6,8 +6,8 @@ body {
font: 15px/22px 'Inter UI', system-ui, sans-serif;
font-size: 15px;
- line-height:1.4;
- /*letter-spacing: 0.009em;*/
+ line-height: 1.5;
+ letter-spacing: -0.002em;
font-weight: 400;
padding-bottom: 30px;
@@ -83,11 +83,11 @@ q:after {
content: "";
}
kbd {
- -moz-font-feature-settings: 'kern' 1, 'case' 1;
- -ms-font-feature-settings: 'kern' 1, 'case' 1;
- -o-font-feature-settings: 'kern' 1, 'case' 1;
+ -moz-font-feature-settings: 'kern' 1, 'case' 1;
+ -ms-font-feature-settings: 'kern' 1, 'case' 1;
+ -o-font-feature-settings: 'kern' 1, 'case' 1;
-webkit-font-feature-settings: 'kern' 1, 'case' 1;
- font-feature-settings: 'kern' 1, 'case' 1;
+ font-feature-settings: 'kern' 1, 'case' 1;
border: 1px solid rgba(0,0,0,0.18);
border-radius: 3px;
padding:0.1em 0.2em;
@@ -98,14 +98,20 @@ dem { /* de-emphasize */
opacity: 0.7;
}
num { /* number */
- -moz-font-feature-settings: 'calt' 1, 'ss01' 1;
- -ms-font-feature-settings: 'calt' 1, 'ss01' 1;
- -o-font-feature-settings: 'calt' 1, 'ss01' 1;
+ /*-moz-font-feature-settings: 'calt' 1, 'ss01' 1;
+ -ms-font-feature-settings: 'calt' 1, 'ss01' 1;
+ -o-font-feature-settings: 'calt' 1, 'ss01' 1;
-webkit-font-feature-settings: 'calt' 1, 'ss01' 1;
- font-feature-settings: 'calt' 1, 'ss01' 1;
+ font-feature-settings: 'calt' 1, 'ss01' 1;*/
+ letter-spacing:0.02em;
white-space: pre;
}
+small {
+ font-size: 11px;
+ letter-spacing: 0.013em;
+}
+
h1, h2, h3 {
font-weight: 500;
-webkit-font-smoothing: antialiased;
@@ -176,11 +182,32 @@ h1 > a, h2 > a, h3 > a {
display: flex;
justify-content: center;
}
-.row > * {
- width:100%;
- max-width: 888px;
- flex: 1 0 100%;
+ .row > * {
+ width:100%;
+ max-width: 888px;
+ flex: 1 0 100%;
+ }
+ .row .learn-more {
+ margin-top: 2em;
+ text-align: center;
+ font-size: 11px;
+ letter-spacing: 0.007em;
+ }
+ .row .learn-more a {
+ color: rgba(0,0,0,0.4);
+ text-decoration-color: rgba(0, 0, 0, 0);
+ }
+ .row .learn-more a:hover {
+ color: inherit;
+ }
+
+.row.full-width {
+ padding: 50px 0;
+ justify-content: flex-start;
}
+ .row.full-width > * {
+ max-width: initial;
+ }
.row-divider {
margin:0 auto;
@@ -228,77 +255,6 @@ h1 > a, h2 > a, h3 > a {
opacity: 1;
}
-/* narrow windows */
-@media only screen and (max-width: 565px) {
- .row.menu ul {
- justify-content: space-between;
- }
- .row.menu ul li {
- margin-right: 15px;
- }
- .row.menu ul li:last-child {
- margin-right: 0;
- }
- .row.menu ul li.home {
- /*color: red;
- clear: both;*/
- /*display: block;*/
- text-align:center;
- margin:0 0 -12px 0;
- width: 100%;
- }
- .row.menu ul li.home > a {
- border-bottom: none;
- padding: 0 1em;
- margin: 0.5em 0;
- line-height:34px;
- border-radius: 90px;
-
- /*color: white;
- background-color: rgba(3, 102, 214, 1);*/
- }
- .row.menu ul li.home > a:hover {
- color: white;
- background-color: #222;
- }
-}
-
-/* small devices (<= iPhone 6+) */
-@media only screen and (max-device-width: 414px) {
- body {
- font-size: 14px;
- line-height: 20px;
- }
- .row {
- padding-left: 20px;
- padding-right: 20px;
- }
- .row.menu ul {
- margin-left: 20px;
- margin-right: 20px;
- }
-}
-
-/* small devices (<= iPhone 5) */
-@media only screen and (max-device-width: 320px) {
- .row.menu {
- font-size:13px;
- }
- .row.menu ul {
- margin-left: 0;
- margin-right: 0;
- }
- .row.menu ul li {
- flex: 1 0 auto;
- text-align: center;
- border-right: 1px solid rgba(0,0,0,0.1);
- margin-left:0;
- margin-right:0;
- }
- .row.menu ul li:last-child {
- border-right: none;
- }
-}
.row.white {
background: white;
@@ -346,13 +302,9 @@ a > img {
}
.sample-images {}
- .sample-images > img, .sample-images > svg {
+ .sample-images img, .sample-images svg {
display: block;
- margin:100px 0;
- width:100%;
- }
- .sample-images > img:first-child, .sample-images > svg:first-child {
- margin-top:50px;
+ width: 100%;
}
@@ -493,16 +445,16 @@ boxes {
}
box {
overflow: auto;
- max-width:100%;
+ flex: 1 1 0;
+ min-width: 280px;
+ max-width: 100%;
display: flex;
flex-direction: column;
background: white;
- padding:2em;
+ padding: 2em;
border-radius: 3px;
margin-right:1em;
margin-bottom:1em;
- flex: 1 1 10%;
- /*width:220px;*/
}
body.safari box {
/* Fix for broken flex wrap in safari */
@@ -514,3 +466,85 @@ box:first-child {
box h3 {
margin-bottom:0.8em;
}
+
+
+/* ------------------------------------------------------ */
+
+/* narrow windows */
+@media only screen and (max-width: 565px) {
+ .row.menu ul {
+ justify-content: space-between;
+ }
+ .row.menu ul li {
+ margin-right: 15px;
+ }
+ .row.menu ul li:last-child {
+ margin-right: 0;
+ }
+ .row.menu ul li.home {
+ /*color: red;
+ clear: both;*/
+ /*display: block;*/
+ text-align:center;
+ margin:0 0 -12px 0;
+ width: 100%;
+ }
+ .row.menu ul li.home > a {
+ border-bottom: none;
+ padding: 0 1em;
+ margin: 0.5em 0;
+ line-height:34px;
+ border-radius: 90px;
+
+ /*color: white;
+ background-color: rgba(3, 102, 214, 1);*/
+ }
+ .row.menu ul li.home > a:hover {
+ color: white;
+ background-color: #222;
+ }
+}
+
+/* small devices (<= iPhone 6+) */
+@media only screen and (max-device-width: 414px) {
+ box { padding: 1em; }
+ box tablex r { font-size: 0.9em; }
+ body {
+ font-size: 14px;
+ line-height: 20px;
+ }
+ .row {
+ padding-left: 20px;
+ padding-right: 20px;
+ }
+ .row.menu ul {
+ margin-left: 20px;
+ margin-right: 20px;
+ }
+}
+
+/* small devices (<= iPhone 5) */
+@media only screen and (max-device-width: 320px) {
+ box {
+ font-size: 0.8em;
+ min-width: 240px;
+ }
+ /*.row.menu {
+ font-size:13px;
+ }
+ .row.menu ul {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .row.menu ul li {
+ flex: 1 0 auto;
+ text-align: center;
+ border-right: 1px solid rgba(0,0,0,0.1);
+ margin-left:0;
+ margin-right:0;
+ }
+ .row.menu ul li:last-child {
+ border-right: none;
+ }*/
+}
+
diff --git a/docs/res/base.js b/docs/res/base.js
new file mode 100644
index 000000000..3ef970cc3
--- /dev/null
+++ b/docs/res/base.js
@@ -0,0 +1,74 @@
+
+function $$(query, el) {
+ return [].slice.call((el || document).querySelectorAll(query))
+}
+
+function $(query, el) {
+ return (el || document).querySelector(query)
+}
+
+// fetchjson(url string) :Promise<Object>
+//
+var fetchjson = (
+ typeof window.fetch == 'function' ? (
+ function _fetchjson(url, cb) {
+ return window.fetch(url).then(function(r) { return r.json() })
+ }
+ ) :
+ function _fetchjson(url, cb) {
+ return new Promise(function(resolve, reject) {
+ var r = new XMLHttpRequest()
+ r.addEventListener("load", function(){
+ try {
+ resolve(JSON.parse(r.responseText))
+ } catch (err) {
+ reject(err)
+ }
+ })
+ r.addEventListener("error", function(ev) {
+ reject(ev.error || ev || new Error('network error'))
+ })
+ r.open("GET", url)
+ r.send()
+ })
+ }
+)
+
+
+// timeNow() :float
+//
+var timeNow = (
+ window.performance !== undefined && window.performance.now ? function() {
+ return window.performance.now()
+ } : Date.now ? function() {
+ return Date.now()
+ } : function() {
+ return (new Date()).getTime()
+ }
+)
+
+
+// Mac or not? Maybe even a buggy Safari?
+var isMac = false
+if (!window.MSStream &&
+ /mac|ipad|iphone|ipod/i.test(navigator.userAgent))
+{
+ isMac = true
+ if (navigator.userAgent.indexOf('Safari') != -1 &&
+ navigator.userAgent.indexOf('Chrome') == -1)
+ {
+ document.body.classList.add('safari')
+ }
+}
+
+
+// Google Analytics
+// ;(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+// (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+// m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+// })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+// ga('create', 'UA-105091131-2', 'auto');
+// ga('send', 'pageview');
+window.dataLayer = window.dataLayer || [];
+window.dataLayer.push(['js', new Date()])
+window.dataLayer.push(['config', 'UA-105091131-2'])
diff --git a/docs/samples/bindings.js b/docs/res/bindings.js
index cac29e417..eb51b87d5 100644
--- a/docs/samples/bindings.js
+++ b/docs/res/bindings.js
@@ -1,11 +1,14 @@
// requires index.js
+function passThrough(v) { return v }
+
function Binding(name){
this.name = name
this.value = undefined
this.inputs = []
this.listeners = []
- this.formatter = undefined
+ this.parser = undefined
+ this.formatter = passThrough
}
@@ -22,7 +25,7 @@ Binding.prototype.addInput = function(el) {
if (this.value === undefined) {
this.value = el.value
} else {
- input.el.value = this.value
+ input.el.value = this.formatter(this.value)
}
el.addEventListener('input', _onInput, {passive:true})
}
@@ -39,8 +42,8 @@ Binding.prototype.addListener = function(listener) {
Binding.prototype.setValue = function(nextval, origin) {
// console.log('Binding.setValue nextval:', nextval, {origin})
var prevval = this.value
- if (this.formatter) {
- nextval = this.formatter(nextval, prevval)
+ if (this.parser) {
+ nextval = this.parser(nextval, prevval)
}
if (this.value === nextval) {
return
@@ -49,7 +52,7 @@ Binding.prototype.setValue = function(nextval, origin) {
this.value = nextval
this.inputs.forEach(function(input) {
if (input.el !== origin) {
- input.el.value = nextval
+ input.el.value = binding.formatter(nextval)
}
})
this.listeners.forEach(function(listener) {
@@ -106,6 +109,11 @@ Bindings.prototype.setValue = function(name, value) {
binding.setValue(value)
}
+Bindings.prototype.setFormatter = function(name, formatter) {
+ var binding = this.getBinding(name)
+ binding.formatter = formatter || passThrough
+}
+
Bindings.prototype.value = function(name, defaultValue) {
var binding = this.bindings[name]
@@ -125,11 +133,11 @@ function fmt_int(nextval, prevval) {
// configure is convenience function for setting value, adding a
-// listener and associating a formatter with a binding.
+// listener and associating a parser with a binding.
// If a listener and a value is provided, the value is set and the listener
// is immediately invoked.
//
-Bindings.prototype.configure = function(name, value, formatter, listener) {
+Bindings.prototype.configure = function(name, value, parser, listener) {
var binding = this.getBinding(name)
if (listener) {
binding.addListener(listener)
@@ -137,23 +145,23 @@ Bindings.prototype.configure = function(name, value, formatter, listener) {
if (value !== undefined && value !== null) {
binding.setValue(value)
}
- if (formatter) {
- if (typeof formatter == 'string') {
- switch (formatter) {
+ if (parser) {
+ if (typeof parser == 'string') {
+ switch (parser) {
case 'number':
case 'float':
- formatter = fmt_float; break;
+ parser = fmt_float; break;
case 'int':
case 'integer':
- formatter = fmt_int; break;
+ parser = fmt_int; break;
default:
- throw new Error('unknown formatter "' + formatter + '"')
+ throw new Error('unknown parser "' + parser + '"')
}
- } else if (typeof formatter != 'function') {
- throw new Error('formatter should be a string or function')
+ } else if (typeof parser != 'function') {
+ throw new Error('parser should be a string or function')
}
- binding.formatter = formatter
+ binding.parser = parser
}
}
diff --git a/docs/favicon.png b/docs/res/favicon.png
index 5caeaf04a..5caeaf04a 100644
--- a/docs/favicon.png
+++ b/docs/res/favicon.png
Binary files differ
diff --git a/docs/res/graphplot.js b/docs/res/graphplot.js
new file mode 100644
index 000000000..b06f67f16
--- /dev/null
+++ b/docs/res/graphplot.js
@@ -0,0 +1,239 @@
+
+function GraphPlot(canvas) {
+ this.canvas = canvas
+ const g = canvas.getContext('2d')
+ if (g == null) {
+ throw new Error('failed to acquire 2d context')
+ }
+
+ this.width = 0 // dp
+ this.height = 0 // dp
+ this.widthPx = 0 // px
+ this.heightPx = 0 // px
+ this.pixelRatio = 1
+ this.g = g
+ this.dataSegments = []
+ this.axes = {
+ x0: .5, // % from left to x=0
+ y0: .5, // % from top to y=0
+ scalex: 40, // pixels from x=0 to x=1
+ scaley: 40, // pixels from y=0 to y=1
+ negativeX: true,
+ }
+
+ if (!this.autosize()) {
+ this.setSize(256, 256)
+ }
+}
+
+GraphPlot.prototype.autosize = function() {
+ try {
+ this.canvas.width = null
+ this.canvas.height = null
+ this.canvas.style.width = null
+ this.canvas.style.height = null
+ var cs = window.getComputedStyle(this.canvas)
+ var width = parseFloat(cs.width)
+ var height = parseFloat(cs.height)
+ this.setSize(width, height)
+ return true
+ } catch (err) {
+ if (typeof console != 'undefined' && console.warn) {
+ console.warn('GraphPlot.autosize failed: ' + err)
+ }
+ }
+ return false
+}
+
+// setOrigin sets the origin of axis x and y
+// The values should be in the range [0-1] and maps to the extremes
+// of the canvas.
+//
+GraphPlot.prototype.setOrigin = function(x, y) {
+ var p = this
+ p.axes.x0 = x
+ p.axes.y0 = y
+}
+
+// setScale sets the value scale for x and y axis.
+// The values should be provided as display points.
+//
+GraphPlot.prototype.setScale = function(x, y) {
+ var p = this
+ if (y === undefined) {
+ y = x
+ }
+ p.axes.scalex = x
+ p.axes.scaley = y
+}
+
+// setSize sets the size of canvas in display points
+//
+GraphPlot.prototype.setSize = function(width, height) {
+ var p = this
+ p.width = width
+ p.height = height
+ const el = p.canvas, g = p.g
+ p.pixelRatio = window.devicePixelRatio || 1
+ if (p.pixelRatio != 1) {
+ el.width = p.widthPx = width * p.pixelRatio
+ el.height = p.heightPx = height * p.pixelRatio
+ g.scale(p.pixelRatio, p.pixelRatio)
+ } else {
+ el.width = p.widthPx = width
+ el.height = p.heightPx = height
+ g.scale(1, 1)
+ }
+ el.style.width = `${width}px`
+ el.style.height = `${height}px`
+}
+
+
+GraphPlot.prototype.renderAxes = function() {
+ var p = this
+ , g = p.g
+ , x0 = Math.round(p.axes.x0 * p.widthPx) / p.pixelRatio
+ , y0 = Math.round(p.axes.y0 * p.heightPx) / p.pixelRatio
+
+ g.beginPath()
+ g.strokeStyle = "rgb(0, 0, 0, 0.2)"
+ if (y0 > 0 && y0 < p.width) {
+ g.moveTo(0, y0); g.lineTo(p.width, y0) // X axis
+ }
+ if (x0 > 0 && x0 < p.height) {
+ g.moveTo(x0, 0); g.lineTo(x0, p.height) // Y axis
+ }
+ g.stroke()
+}
+
+
+// plotf plots an arbitrary function on the graph
+//
+GraphPlot.prototype.plotf = function(f, color) {
+ var p = this
+ , g = p.g
+ , w = p.width
+ , h = p.height
+ , x0 = p.axes.x0 * p.width
+ , y0 = p.axes.y0 * p.height
+ , x = 0
+ , y = 0
+ , dx = 4 / p.pixelRatio // smaller means finer curves and more CPU
+ , scalex = p.axes.scalex * w
+ , scaley = p.axes.scaley * h
+ , iMax = Math.round((w - x0) / dx)
+ , iMin = p.axes.negativeX ? Math.round(-x0 / dx) : 0
+
+ g.beginPath()
+ g.lineWidth = 1
+ g.strokeStyle = color || "rgb(0, 0, 0, 0.8)"
+
+ for (var i = iMin; i <= iMax; i++) {
+ x = dx * i
+ y = f(x / scalex) * scaley
+ if (i == iMin) {
+ g.moveTo(x0 + x, y0 - y)
+ } else {
+ g.lineTo(x0 + x, y0 - y)
+ }
+ }
+
+ g.stroke()
+}
+
+
+// plotLines draws straight lines between a collection of points
+//
+GraphPlot.prototype.plotLine = function(points, color) {
+ var p = this
+ , g = p.g
+ , x0 = p.axes.x0 * p.width
+ , y0 = p.axes.y0 * p.height
+ , x = 0
+ , y = 0
+ , scalex = p.axes.scalex * p.width
+ , scaley = p.axes.scaley * p.height
+ , pt
+
+ g.beginPath()
+ g.lineWidth = 1
+ g.strokeStyle = color || "rgb(0, 0, 0, 0.8)"
+
+ var i = 0
+ for (; i < points.length; i++) {
+ pt = points[i]
+ x = pt[0] * scalex
+ y = pt[1] * scaley
+ if (i == 0) {
+ g.moveTo(x0 + x, y0 - y)
+ } else {
+ g.lineTo(x0 + x, y0 - y)
+ }
+ }
+
+ g.stroke()
+}
+
+
+// plotPoints draws points
+//
+GraphPlot.prototype.plotPoints = function(points, color) {
+ var p = this
+ , g = p.g
+ , x0 = p.axes.x0 * p.width
+ , y0 = p.axes.y0 * p.height
+ , x = 0
+ , y = 0
+ , scalex = p.axes.scalex * p.width
+ , scaley = p.axes.scaley * p.height
+ , pt
+ , i = 0
+
+ g.fillStyle = color || "rgb(0, 0, 0, 0.8)"
+
+ for (; i < points.length; i++) {
+ pt = points[i]
+ x = x0 + pt[0] * scalex
+ y = y0 - pt[1] * scaley
+ g.beginPath()
+ g.arc(x, y, 3, 0, Math.PI + (Math.PI * 2) / 2, false)
+ g.fill()
+ }
+}
+
+
+GraphPlot.prototype.clear = function() {
+ var p = this
+ p.g.clearRect(0, 0, p.width, p.height)
+ p.renderAxes()
+}
+
+
+GraphPlot.prototype.renderDemo = function() {
+ var p = this
+ , g = p.g
+ , dpscale = p.pixelRatio
+ , w = p.widthPx
+ , h = p.heightPx
+
+ p.clear()
+
+ p.plotf(
+ function(x) { return Math.sin(x) },
+ 'blue'
+ )
+
+ p.plotf(
+ function(x) { return Math.cos(3*x) },
+ 'hotpink'
+ )
+
+ // var scale = p.height / 4
+ // g.moveTo(0, scale)
+ // var i, sine, lines = 200, frag = p.width / lines
+ // for (i = 0; i < lines; i++) {
+ // sine = Math.sin(i / scale * 2) * scale
+ // g.lineTo(i * frag, -sine + scale)
+ // }
+ // g.stroke()
+}
diff --git a/docs/samples/index.css b/docs/samples/index.css
new file mode 100644
index 000000000..2203be989
--- /dev/null
+++ b/docs/samples/index.css
@@ -0,0 +1,243 @@
+body {
+ padding-bottom: 0;
+ background: white;
+}
+
+.row.footer h2 {
+ margin:0;
+ text-align:center;
+}
+
+livesample {
+ display: block;
+ color: #111;
+ outline: none;
+ padding-left: 20px;
+ border-left: 2px solid transparent;
+ margin-left:-22px;
+ margin-top: 1em;
+ margin-bottom: 1.6em;
+}
+livesample:hover {
+ /*color: rgb(3, 102, 214);*/
+ border-left-color: rgb(3, 102, 214);
+}
+livesample:focus {
+ border-left-color: #eee;
+}
+livesample > p {
+ margin-top: 0;
+}
+livesample.s1 {
+ padding-left: 16px;
+ letter-spacing: -0.01em;
+ font-size: 5em;
+ font-weight: 600;
+ line-height: 1.1;
+ margin-top: 0;
+ margin-bottom: 0.3em;
+}
+livesample.s2 {
+ max-width: 400px;
+ font-size: 1em;
+}
+livesample.s3 {
+ font-size: 13px;
+ line-height: 18px;
+}
+ livesample.s3 b, livesample.s3 strong {
+ font-weight:500;
+ color: black;
+ }
+
+livesample.col3 {
+ -moz-column-width: 20em;
+ -moz-columns: 20em;
+ -webkit-columns: 20em;
+ columns: 20em;
+
+ -moz-column-gap: 2em;
+ -webkit-column-gap: 2em;
+ column-gap: 2em;
+}
+livesample.col2 {
+ -moz-column-count: 2;
+ -webkit-column-count: 2;
+ column-count: 2;
+}
+
+.font-style-regular { font-weight:400 !important; font-style:normal !important; }
+.font-style-italic { font-weight:400 !important; font-style:italic !important; }
+.font-style-medium { font-weight:500 !important; font-style:normal !important; }
+.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
+.font-style-bold { font-weight:700 !important; font-style:normal !important; }
+.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
+.font-style-black { font-weight:900 !important; font-style:normal !important; }
+.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
+
+div.live {
+ margin-top:1em;
+ margin-bottom:100px;
+ padding-bottom:20px;
+ border-bottom: 1px solid #ddd;
+}
+ div.live .learn-more {
+ margin-top:40px;
+ user-select: none;
+ }
+ div.controls {
+ position: absolute;
+ right: 0;
+ top: 150px;
+ width: 250px;
+ padding: 10px 0;
+ /*background:#eee;*/
+ opacity:0.3;
+ transition: 90ms opacity cubic-bezier(0.25, 0.47, 0.44, 0.93);
+ /*border:1px solid #bbb;*/
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+ border-right:none;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ font-size: 13px;
+ }
+ div.controls:hover {
+ opacity:1;
+ background:#f5f5f5;
+ border-color: transparent;
+ }
+ div.controls .control {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ overflow: hidden;
+ min-height: 30px;
+ margin: 0 16px;
+ }
+ div.controls .control > * {
+ flex: 1 1 auto;
+ margin:0;
+ margin-right: 16px;
+ box-sizing: border-box;
+ }
+ div.controls .control > :last-child {
+ margin-right: 0;
+ }
+ div.controls .control > select {
+ min-width: 6em;
+ align-items: center;
+ justify-content: center;
+ }
+ div.controls .control > input,
+ div.controls .control > select {
+ width: 0;
+ outline: none;
+ }
+ div.controls .control > input[type="number"],
+ div.controls .control > input[type="text"] {
+ background: none;
+ border: none;
+ padding: 4px 0;
+ font-size: inherit;
+ /*border-radius: 2px;*/
+ }
+ div.controls .control > input[type="number"] {
+ max-width: 48px;
+ text-align: right;
+ -moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ -webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
+ }
+ div.controls .control > input[type=number]::-webkit-inner-spin-button,
+ div.controls .control > input[type=number]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+ div.controls .control > input[type="range"] {
+ /*max-width: 80%;*/
+ flex: 1 1 auto;
+ display: block;
+ }
+ div.controls .control > img.icon,
+ div.controls .control > label {
+ font-family: georgia, serif;
+ font-style: italic;
+ color: black;
+ width: 16px;
+ height: 16px;
+ flex: 0 0 auto;
+ margin-right: 16px;
+ opacity: 0.6;
+ }
+ div.controls canvas {
+ height: 200px;
+ }
+ div.controls .control.info,
+ div.controls canvas {
+ transition: 390ms opacity cubic-bezier(0.25, 0.47, 0.44, 0.93);
+ opacity: 0;
+ }
+ div.controls:hover .control.info,
+ div.controls:hover canvas {
+ opacity: 1;
+ }
+
+
+/* narrow windows */
+@media only screen and (max-width: 1200px) {
+ div.controls {
+ width: 210px;
+ font-size: 12px;
+ }
+}
+@media only screen and (max-width: 1024px) {
+ div.controls {
+ width: 140px;
+ font-size: 11px;
+ }
+ div.controls canvas {
+ display: none;
+ }
+ div.controls .control.info {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ }
+ div.controls .control > input[type="range"] {
+ width: 0;
+ flex: 0 1 0%;
+ display: none;
+ }
+ div.controls .control > input[type="number"] {
+ max-width: 100%;
+ flex: 1 1 auto;
+ }
+}
+@media only screen and (max-width: 740px) {
+ livesample.s1 {
+ font-size:4.5em;
+ }
+ div.controls {
+ display: none;
+ }
+}
+@media only screen and (max-width: 565px) {
+ livesample.s1 {
+ font-size:4em;
+ }
+}
+@media only screen and (max-width: 414px) {
+ livesample.s1 {
+ font-size:3.4em;
+ }
+}
+
+.sample-images img, .sample-images svg {
+ margin: 100px 0;
+}
+.sample-images > img:first-child, .sample-images > svg:first-child {
+ margin-top:50px;
+}
diff --git a/docs/samples/index.html b/docs/samples/index.html
index 08de84f72..a56b6aa60 100644
--- a/docs/samples/index.html
+++ b/docs/samples/index.html
@@ -1,300 +1,73 @@
-<!DOCTYPE HTML>
-<html lang="en" prefix="og: http://ogp.me/ns#">
- <head>
- <meta charset="utf-8">
- <title>Inter UI font family</title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta property="og:title" content="Inter UI font family">
- <meta property="twitter:title" content="Inter UI font family">
- <meta property="description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="og:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:description" content="Inter UI is a new typeface optimized for computer user interfaces">
- <meta property="twitter:card" content="summary">
- <meta property="twitter:site" content="@rsms">
- <meta property="twitter:creator" content="@rsms">
- <meta property="og:image" content="https://rsms.me/inter/res/poster.png">
- <meta property="twitter:image" content="https://rsms.me/inter/res/poster.png">
- <meta property="fb:app_id" content="38027689216">
- <meta property="og:url" content="https://rsms.me/inter/">
- <meta property="og:site_name" content="rsms.me">
- <meta property="og:type" content="product">
- <meta property="og:locale" content="en_US" />
- <meta name="format-detection" content="telephone=no">
- <link rel="icon" type="image/png" href="../favicon.png" />
- <link href="../inter-ui.css?v=2.5" rel="stylesheet">
- <link href="../index.css?v=5" rel="stylesheet">
- <style type="text/css">
-body {
- padding-bottom: 0;
- background: white;
-}
-
-.row.footer h2 {
- margin:0;
- text-align:center;
-}
-
-/*.row.menu {
- background: white;
-}*/
-
-livesample {
- display: block;
- color: #111;
- outline: none;
- padding-left: 20px;
- border-left: 2px solid transparent;
- margin-left:-22px;
- margin-top: 1em;
- margin-bottom: 1.6em;
-}
-livesample:hover {
- /*color: rgb(3, 102, 214);*/
- border-left-color: rgb(3, 102, 214);
-}
-livesample:focus {
- border-left-color: #eee;
-}
-livesample > p {
- margin-top: 0;
-}
-livesample.s1 {
- padding-left: 16px;
- letter-spacing: -0.005em;
- font-size: 5em;
- font-weight: 600;
- line-height: 1.1;
- margin-top: 0;
- margin-bottom: 0.3em;
-}
-livesample.s2 {
- max-width: 400px;
- font-size: 1em;
-}
-livesample.s3 {
- font-size: 13px;
- line-height: 18px;
-}
- livesample.s3 b, livesample.s3 strong {
- font-weight:500;
- color: black;
- }
-
-livesample.col3 {
- -moz-column-width: 20em;
- -moz-columns: 20em;
- -webkit-columns: 20em;
- columns: 20em;
-
- -moz-column-gap: 2em;
- -webkit-column-gap: 2em;
- column-gap: 2em;
-}
-livesample.col2 {
- -moz-column-count: 2;
- -webkit-column-count: 2;
- column-count: 2;
-}
-
-.font-style-regular { font-weight:400 !important; font-style:normal !important; }
-.font-style-italic { font-weight:400 !important; font-style:italic !important; }
-.font-style-medium { font-weight:500 !important; font-style:normal !important; }
-.font-style-medium-italic { font-weight:500 !important; font-style:italic !important; }
-.font-style-bold { font-weight:700 !important; font-style:normal !important; }
-.font-style-bold-italic { font-weight:700 !important; font-style:italic !important; }
-.font-style-black { font-weight:900 !important; font-style:normal !important; }
-.font-style-black-italic { font-weight:900 !important; font-style:italic !important; }
-
-div.live {
- margin-top:1em;
- margin-bottom:100px;
- padding-bottom:100px;
- border-bottom: 1px solid #ddd;
-}
- div.controls {
- position: absolute;
- right: 0;
- top: 150px;
- width: 220px;
- padding: 10px 16px;
- /*background:#eee;*/
- opacity:0.3;
- border:1px solid #bbb;
- border-top-left-radius: 5px;
- border-bottom-left-radius: 5px;
- border-right:none;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
- div.controls:hover {
- opacity:1;
- background:#f5f5f5;
- border-color: transparent;
- }
- div.controls .control {
- display: flex;
- justify-content: space-between;
- align-items: center;
- overflow: hidden;
- height:30px;
- }
- div.controls .control > * {
- /*max-width: 50%;*/
- flex: 1 1 auto;
- margin:0;
- margin-right: 16px;
- box-sizing: border-box;
- }
- div.controls .control > :last-child {
- margin-right: 0;
- }
- div.controls .control > select {
- min-width: 6em;
- align-items: center;
- justify-content: center;
- }
- div.controls .control > input,
- div.controls .control > select {
- width: 0;
- outline: none;
- }
- div.controls .control > input[type="number"],
- div.controls .control > input[type="text"] {
- background: none;
- border: none;
- padding: 4px 0;
- font-size: 13px;
- /*border-radius: 2px;*/
- }
- div.controls .control > input[type="number"] {
- max-width: 60px;
- text-align: right;
- -moz-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
- -ms-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
- -o-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
- -webkit-font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
- font-feature-settings: 'calt' 1, 'zero' 1, 'tnum' 1;
- }
- div.controls .control > input[type="range"] {
- /*max-width: 80%;*/
- flex: 1 1 auto;
- display: block;
- }
- div.controls .control > img.icon {
- width: 16px;
- height: 16px;
- flex: 0 0 auto;
- margin-right: 16px;
- opacity: 0.8;
- }
-
- /*div.controls .control > input.foo {
- background-color: hotpink;
- border:none;
- border-radius: 90px;
- }*/
-
-
-/* narrow windows */
-@media only screen and (max-width: 1200px) {
- div.live div.controls {
- width: 200px;
- }
-}
-@media only screen and (max-width: 1024px) {
- div.live div.controls {
- width: 100px;
- }
- div.controls .control > input[type="range"] {
- width: 0;
- flex: 0 1 0%;
- display: none;
- }
- div.controls .control > input[type="number"] {
- max-width: 100%;
- flex: 1 1 auto;
- }
-}
-@media only screen and (max-width: 740px) {
- livesample.s1 {
- font-size:4.5em;
- }
- div.live div.controls {
- display: none;
- }
-}
-@media only screen and (max-width: 565px) {
- livesample.s1 {
- font-size:4em;
- }
-}
-@media only screen and (max-width: 414px) {
- livesample.s1 {
- font-size:3.4em;
- }
-}
- </style>
- </head>
- <body>
-
- <div class="row menu">
- <ul class="menu">
- <li class="home"><a href="../">Inter UI</a></li>
- <li><a class="download-link"
- href="https://github.com/rsms/inter/releases/latest/"
- >Download</a></li>
- <li><a href="/inter/samples/" class="active">Samples</a></li>
- <li><a href="../lab/">Playground</a></li>
- <li><a href="https://github.com/rsms/inter/">Source</a></li>
- </ul>
+---
+layout: default
+title: Samples
+---
+{%
+
+capture url_root
+ %}{% if site.safe == false %}/{% else %}/inter/{% endif
+%}{%
+endcapture %}{%
+
+for file in site.static_files %}{%
+ assign _path = file.path | remove_first: "/inter" %}{%
+ if _path == "/samples/index.css" %}{%
+ assign index_css_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/res/bindings.js" %}{%
+ assign bindings_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ elsif _path == "/res/graphplot.js" %}{%
+ assign graphplot_js_v = file.modified_time | date: "%Y%m%d%H%M%S" %}{%
+ endif %}{%
+endfor
+
+%}
+<link rel="stylesheet" href="index.css?v={{ index_css_v }}">
+<script src="{{url_root}}res/bindings.js?v={{ bindings_js_v }}"></script>
+<script src="{{url_root}}res/graphplot.js?v={{ graphplot_js_v }}"></script>
+
+<div class="row"><div>
+ <div class="live">
+
+ <div class="controls">
+ <div class="control">
+ <img title="Style" class="icon" src="icons/style.svg">
+ <select data-binding="style">
+ <option value="regular" default>Regular</option>
+ <option value="italic">Italic</option>
+ <option value="medium" default>Medium</option>
+ <option value="medium-italic">Medium Italic</option>
+ <option value="bold" default>Bold</option>
+ <option value="bold-italic">Bold Italic</option>
+ <option value="black" default>Black</option>
+ <option value="black-italic">Black Italic</option>
+ </select>
+ </div>
+ <div class="control">
+ <img title="Size" class="icon" src="icons/font-size.svg">
+ <input type="range" min="8" max="100" step="1" data-binding="font-size">
+ <input type="number" min="4" max="400" step="1" data-binding="font-size">
+ </div>
+ <div class="control">
+ <img title="Letter spacing in EM" class="icon" src="icons/letter-spacing.svg">
+ <input type="range" min="-0.05" max="0.06" step="0.001" data-binding="letter-spacing">
+ <input type="number" min="-0.15" max="1" step="0.001" data-binding="letter-spacing">
+ </div>
+ <canvas class="graphplot">Canvas not Supported</canvas>
+ <div class="control info">
+ <a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics</a>
+ </div>
</div>
- <div class="row white"><div>
- <div class="live">
-
- <div class="controls">
- <div class="control">
- <img title="Style" class="icon" src="icons/style.svg">
- <select data-binding="style">
- <option value="regular" default>Regular</option>
- <option value="italic">Italic</option>
- <option value="medium" default>Medium</option>
- <option value="medium-italic">Medium Italic</option>
- <option value="bold" default>Bold</option>
- <option value="bold-italic">Bold Italic</option>
- <option value="black" default>Black</option>
- <option value="black-italic">Black Italic</option>
- </select>
- </div>
- <div class="control">
- <img title="Size" class="icon" src="icons/font-size.svg">
- <input type="range" min="8" max="100" step="1" data-binding="font-size">
- <input type="number" min="4" max="400" step="1" data-binding="font-size">
- </div>
- <div class="control">
- <img title="Letter spacing in EM" class="icon" src="icons/letter-spacing.svg">
- <input type="range" min="-0.05" max="0.06" step="0.001" data-binding="letter-spacing">
- <input type="number" min="-0.15" max="1" step="0.001" data-binding="letter-spacing">
- </div>
- <!-- <div class="control">
- <img class="icon" src="icons/font-size.svg">
- <input type="text" class="foo" data-binding="foo">
- <input type="text" class="foo" data-binding="foo">
- </div> -->
- </div>
+ <livesample contenteditable class="s1">
+ Fabulous typography encountering spring
+ </livesample>
- <livesample contenteditable class="s1">
- Fabulous typography encountering spring
- </livesample>
+ <livesample contenteditable class="s2">
+ The user interface (UI), in the industrial design field of human-computer
+ interaction, is the space where interactions between humans and machines occur.
+ </livesample>
- <livesample contenteditable class="s2">
- The user interface (UI), in the industrial design field of human-computer
- interaction, is the space where interactions between humans and machines occur.
- </livesample>
-
- <livesample contenteditable class="s3 col3">
+ <livesample contenteditable class="s3 col3">
<p><b>Fire Island Beach</b> is a barrier of sand, stretching for twenty miles
along the south coast of Long Island, and separating the Great South Bay
from the Atlantic ocean.
@@ -350,89 +123,67 @@ When the tide is on the right moon and the wind has blown a gale from
the southeast, the strand is entirely submerged, and people upon the
main shore three miles away can see the surf breaking over the Beach
hills.
-</p><p>
-Such a riot of sea and wind strews the whole extent of beach with
-whatever has been lost or thrown overboard, or torn out of sunken ships.
-Many a man has made a good week’s work in a single day by what he has
-found while walking along the Beach when the surf was down.
-</p><p>
-“The Captain” knew all this and had patrolled that Beach scores of
-times.
-</p><p>
-Ten years had passed since the first time which laid the habit of
-wandering along the surf-shore apparently in search of whatever the sea
-had cast up. Sometimes a spar, sometimes sheets of copper torn from a
-wreck and carried by a high surf far along the strand, sometimes a
-vessel’s gilded name, at other times only scattered drift-wood were the
-rewards of these lonely walks.
</p>
- </livesample>
- </div>
-
- <p class="sample-images">
- <img src="img/01.png" srcset="img/01@2x.png 2x" width="888">
- <img src="img/02.png" srcset="img/02@2x.png 2x" width="888">
- <!-- <img src="img/02.svg" width="888"> -->
- <img src="img/03.png" srcset="img/03@2x.png 2x" width="888">
- <img src="img/04.png" srcset="img/04@2x.png 2x" width="888">
- <img src="img/05.png" srcset="img/05@2x.png 2x" width="888">
- <img src="img/dark-phone.jpg" srcset="img/dark-phone@2x.jpg 2x" width="888">
- <img src="img/06.png" srcset="img/06@2x.png 2x" width="888">
- <img src="img/07.png" srcset="img/07@2x.png 2x" width="888">
- <img src="img/08.png" srcset="img/08@2x.png 2x" width="888">
- <img src="img/09.png" srcset="img/09@2x.png 2x" width="888">
- <img src="img/10.png" srcset="img/10@2x.png 2x" width="888">
- <img src="img/11.png" srcset="img/11@2x.png 2x" width="888">
- <img src="img/12.png" srcset="img/12@2x.png 2x" width="888">
- <img src="img/13.png" srcset="img/13@2x.png 2x" width="888">
- <img src="img/14.png" srcset="img/14@2x.png 2x" width="888">
- <img src="img/15.png" srcset="img/15@2x.png 2x" width="888">
- </p>
- <p style="text-align:center">
- <a href="https://www.figma.com/file/WmU5NWr52bnUcqv5os0V4sWi/" class="plain">Open these samples in Figma</a>
- </p>
- </div></div>
-
- <script src="../index.js?v=2"></script>
- <script src="bindings.js"></script>
- <script type="text/javascript">(function(){
-
-
-
-// InterUIDynamicTracking takes the font size in points or pixels and returns
-// the compensating tracking in EM.
+ </livesample>
+ <p class="learn-more">
+ &nbsp;
+ <!-- <a href="{{url_root}}dynmetrics/">Learn about Dynamic Metrics</a> -->
+ </p>
+ </div>
+
+ <p class="sample-images">
+ <img src="img/01.png" srcset="img/01@2x.png 2x" width="888">
+ <img src="img/02.png" srcset="img/02@2x.png 2x" width="888">
+ <!-- <img src="img/02.svg" width="888"> -->
+ <img src="img/03.png" srcset="img/03@2x.png 2x" width="888">
+ <img src="img/04.png" srcset="img/04@2x.png 2x" width="888">
+ <img src="img/05.png" srcset="img/05@2x.png 2x" width="888">
+ <img src="img/dark-phone.jpg" srcset="img/dark-phone@2x.jpg 2x" width="888">
+ <img src="img/06.png" srcset="img/06@2x.png 2x" width="888">
+ <img src="img/07.png" srcset="img/07@2x.png 2x" width="888">
+ <img src="img/08.png" srcset="img/08@2x.png 2x" width="888">
+ <img src="img/09.png" srcset="img/09@2x.png 2x" width="888">
+ <img src="img/10.png" srcset="img/10@2x.png 2x" width="888">
+ <img src="img/11.png" srcset="img/11@2x.png 2x" width="888">
+ <img src="img/12.png" srcset="img/12@2x.png 2x" width="888">
+ <img src="img/13.png" srcset="img/13@2x.png 2x" width="888">
+ <img src="img/14.png" srcset="img/14@2x.png 2x" width="888">
+ <img src="img/15.png" srcset="img/15@2x.png 2x" width="888">
+ </p>
+ <p style="text-align:center">
+ <a
+ href="https://www.figma.com/file/WmU5NWr52bnUcqv5os0V4sWi/"
+ class="plain">Open these samples in Figma</a>
+ </p>
+</div></div>
+
+<script type="text/javascript">(function(){
+
+
+
+// InterUIDynamicTracking produces tracking in EM for the given font size
//
function InterUIDynamicTracking(fontSize, weightClass) {
// if (!weightClass) { -- currently unused
// weightClass = 400
// }
//
- // y = -0.01021241 + 0.3720623 * e ^ (-0.2808687 * x)
- // [6-35] 0.05877 .. -0.0101309 (13==0; stops growing around 30-35)
- // See https://gist.github.com/rsms/8efdbca5f8145a584ed08a7c3d6e5788
- //
- return -0.01021241 + 0.3720623 * Math.pow(Math.E, (-0.2808687 * fontSize))
-
- // y = 0.025 - (ln(x) * 0.01)
- // return 0.025 - Math.log(fontSize) * 0.01
+ var a = -0.0149, b = 0.298, c = -0.23;
+ return a + b * Math.pow(Math.E, (c * fontSize))
}
-
-function InterUIDynamicLeading(fontSize, weightClass) {
- var lineHeight = Math.round(fontSize * 1.4)
- //
- // TODO
- //
- // console.log(
- // 'lineHeight:', lineHeight,
- // `(${Math.round(fontSize * 1.45)})`,
- // )
-
- return lineHeight
+// InterUIDynamicLineHeight produces the line height for the given font size
+//
+function InterUIDynamicLineHeight(fontSize, weightClass) {
+ var l = 1.4
+ return Math.round(fontSize * l)
}
var bindings = new Bindings()
+var graph = new GraphPlot($('canvas.graphplot'))
+graph.setOrigin(-0.2, 0.8)
+graph.setScale(0.049, 5)
var s2 = $('livesample.s2')
@@ -443,22 +194,39 @@ function updateWidth() {
s2.style.maxWidth = Math.round(w) + 'px'
}
+function updateTracking() {
+ var fontSize = bindings.value('font-size', 0)
+ var letterSpacing = InterUIDynamicTracking(fontSize, 400)
+ bindings.setValue('letter-spacing', letterSpacing)
+}
+
+function updateGraph() {
+ graph.clear()
+ var fontSize = bindings.value('font-size', 0)
+ var letterSpacing = bindings.value('letter-spacing')
+ graph.plotf(function(x) {
+ return InterUIDynamicTracking(x, 400)
+ })
+ var graphedFontSize = Math.min(24, fontSize) // clamp to [-inf,24]
+ graph.plotPoints([[graphedFontSize, letterSpacing]], '#000')
+}
+
bindings.configure('letter-spacing', 0, 'float', function (letterSpacing) {
s2.style.letterSpacing = letterSpacing + 'em'
updateWidth()
+ updateGraph()
+})
+bindings.setFormatter('letter-spacing', function(v) {
+ return v.toFixed(3)
})
-bindings.configure('font-size', 18, 'int', function(fontSize, prevval) {
+bindings.configure('font-size', 16, 'float', function(fontSize, prevval) {
s2.style.fontSize = fontSize + 'px'
updateWidth()
+ updateTracking()
- var letterSpacing = InterUIDynamicTracking(fontSize, 400)
- letterSpacing = parseFloat(letterSpacing.toFixed(3)) // lower precision
-
- var lineHeight = InterUIDynamicLeading(fontSize, 400)
+ var lineHeight = InterUIDynamicLineHeight(fontSize, 400)
s2.style.lineHeight = lineHeight + 'px'
-
- bindings.setValue('letter-spacing', letterSpacing)
})
bindings.configure('style', null, null, function (style) {
@@ -478,8 +246,14 @@ bindings.configure('style', null, null, function (style) {
bindings.bindAllInputs('div.live .control input')
bindings.bindAllInputs('div.live .control select')
-
-
- })();</script>
- </body>
-</html>
+// resize canvas when window resizes
+var resizeDebounceTimer = null
+window.addEventListener('resize', function(){
+ clearTimeout(resizeDebounceTimer)
+ resizeDebounceTimer = setTimeout(function(){
+ graph.autosize()
+ updateGraph()
+ }, 500)
+}, {passive:true, capture:false})
+
+})();</script>
diff --git a/docs/serve.sh b/docs/serve.sh
deleted file mode 100755
index b10c7649f..000000000
--- a/docs/serve.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-set -e
-cd "$(dirname "$0")"
-
-if [ ! -s lab/fonts ]; then
- ln -s ../../build/dist lab/fonts
-fi
-
-if (which caddy >/dev/null); then
- caddy_args=(\
- -host localhost \
- "bind localhost" \
- "mime .woff2 font/woff2" \
- "mime .woff application/font-woff" \
- )
- caddy "${caddy_args[@]}"
-elif (which servedir >/dev/null); then
- servedir
-else
- echo "Can not find 'caddy' nor 'servedir' in PATH." >&2
- echo "Install caddy from brew, apt or https://caddyserver.com/download"
- echo "or install servedir with 'npm install -g secure-servedir'"
- exit 1
-fi
diff --git a/misc/fontinfo.py b/misc/fontinfo.py
index 17ee4f521..9d0eb3fb0 100755
--- a/misc/fontinfo.py
+++ b/misc/fontinfo.py
@@ -7,6 +7,7 @@ import os
import sys
import argparse
import json
+import re
from base64 import b64encode
from fontTools import ttLib
@@ -288,6 +289,13 @@ def genFontInfo(fontpath, outputType, withGlyphs=True):
if 'subfamilyName' in nameDict:
info['name'] += '-' + nameDict['subfamilyName'].replace(' ', '')
+ if 'version' in nameDict:
+ version = nameDict['version']
+ v = re.split(r'[\s;]+', version)
+ if v and len(v) > 0:
+ version = v[0]
+ info['version'] = version
+
if outputType is not OUTPUT_TYPE_GLYPHLIST:
if len(nameDict):
info['names'] = nameDict
@@ -425,7 +433,7 @@ def main():
args = argparser.parse_args()
- fonts = {}
+ fonts = []
outputType = OUTPUT_TYPE_COMPLETE
if args.asGlyphList:
outputType = OUTPUT_TYPE_GLYPHLIST
@@ -437,7 +445,7 @@ def main():
# internal cache that mixes up values for different fonts.
reload(sstruct)
font = genFontInfo(fontpath, outputType=outputType, withGlyphs=args.withGlyphs)
- fonts[font['id']] = font
+ fonts.append(font)
n += 1
ostream = sys.stdout
@@ -447,6 +455,7 @@ def main():
if args.prettyJson:
json.dump(fonts, ostream, sort_keys=True, indent=2, separators=(',', ': '))
+ sys.stdout.write('\n')
else:
json.dump(fonts, ostream, separators=(',', ':'))