From 9f367901ef4e6df00eb786ac99fcdc21ed5e69f0 Mon Sep 17 00:00:00 2001 From: Rasmus Andersson Date: Tue, 20 Feb 2018 01:38:51 -0800 Subject: [PATCH] website: major update --- .gitignore | 1 + Makefile | 6 +- docs/_config.yml | 10 + docs/{info.json => _data/fontinfo.json} | 9 +- docs/_includes/autoreload-in-debug.html | 46 ++ docs/_layouts/default.html | 88 ++++ docs/{ => _scripts}/optimize-resources.sh | 2 +- docs/_scripts/serve.sh | 9 + docs/dynmetrics/index.css | 262 ++++++++++ docs/dynmetrics/index.html | 522 +++++++++++++++++++ docs/glyphs/index.html | 111 ++-- docs/index.html | 606 ++++++++++------------ docs/index.js | 138 ----- docs/{index.css => res/base.css} | 224 ++++---- docs/res/base.js | 74 +++ docs/{samples => res}/bindings.js | 40 +- docs/{ => res}/favicon.png | Bin docs/res/graphplot.js | 239 +++++++++ docs/samples/index.css | 243 +++++++++ docs/samples/index.html | 502 +++++------------- docs/serve.sh | 24 - misc/fontinfo.py | 13 +- 22 files changed, 2139 insertions(+), 1030 deletions(-) create mode 100644 docs/_config.yml rename docs/{info.json => _data/fontinfo.json} (98%) create mode 100644 docs/_includes/autoreload-in-debug.html create mode 100644 docs/_layouts/default.html rename docs/{ => _scripts}/optimize-resources.sh (96%) create mode 100755 docs/_scripts/serve.sh create mode 100644 docs/dynmetrics/index.css create mode 100644 docs/dynmetrics/index.html delete mode 100644 docs/index.js rename docs/{index.css => res/base.css} (87%) create mode 100644 docs/res/base.js rename docs/{samples => res}/bindings.js (77%) rename docs/{ => res}/favicon.png (100%) create mode 100644 docs/res/graphplot.js create mode 100644 docs/samples/index.css delete mode 100755 docs/serve.sh 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 similarity index 98% rename from docs/info.json rename to 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 %} + + +{% 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 + +%} + + + + {% if page.title %}{{ page.title }} — Inter UI{% else %}Inter UI font family{% endif %} + + + + + + + + + + + + + + {% if page.title %} + + + {% endif %} + {% if page.og_image_url %} + + + {% else %} + + + {% endif %} + + + + + + + + + + + + {{ content }} + + {% if site.safe == true %} + + {% endif %} + {% include autoreload-in-debug.html %} + + diff --git a/docs/optimize-resources.sh b/docs/_scripts/optimize-resources.sh similarity index 96% rename from docs/optimize-resources.sh rename to 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 + +%} + + + + +
+

Dynamic Metrics

+

+ 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 good 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: +

+

+ + tracking = + a + b × + e(c × fontSize) + + + leading = l × fontSize + + + e2.718 + +

+

+ View this on a larger screen to enable interactive control. +

+
+ + + +
+ +
+

+ + 15   0.0   ( 0.0 ) + 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. +

+
+ + + +
+ + + 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 @@ - - - - - Repertoire – Inter UI font family +--- +layout: default +title: Glyphs +--- +{% - - +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 == "/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 - - - - - - +%} - - - - - - - - -
+ +
@@ -2222,37 +2210,34 @@
-
-

The Inter UI font family

-

Inter UI glyphs

-

- This shows the complete set of glyphs in Inter UI Regular. - You can zoom in and out by pressing - + and - on your keyboard. - Click on a glyph to see more details about it. -

-
+
+

Glyphs

+

+ This shows the complete set of glyphs in Inter UI Regular. + You can zoom in and out by pressing + + and + on your keyboard. + Click on a glyph to see more details about it. +

+
-
- -
+
+ +
-
-

Kerning

-
-
+
+

Kerning

+
+
- - - + 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 @@ - - - - - Inter UI font family - - - - - - - - - - - - - - - - - - - - - - - +--- +layout: default +--- - +
+

The Inter UI font family

+

+ Inter UI is a typeface specially designed for user interfaces + with focus on high legibility of small-to-medium sized text on computer screens. +

+

+ 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. +

+
-
-

The Inter UI font family

-

- Inter UI is a typeface specially designed for user interfaces - with focus on high legibility of small-to-medium sized text on computer screens. -

-

- 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. -

-
+
+

+ +

+

+ More samples -> +

+

+
-
-

- -

-

- More samples -> -

-

-
+
-
+

How do I use it?

+

+ Using the font is as easy as + download & installing locally on your computer. +

+

+ 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: +

+ @import url('https://rsms.me/inter/inter-ui.css'); +

Use the following CSS rules to specify the Inter UI family:

+ font-family: 'Inter UI', sans-serif; -

How do I use it?

-

- Using the font is as easy as - download & installing locally on your computer. -

-

- 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: -

- @import url('https://rsms.me/inter/inter-ui.css'); -

Use the following CSS rules to specify the Inter UI family:

- font-family: 'Inter UI', sans-serif; +

 

-

 

+

Dynamic Metrics

+

+ 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 good typography. You simply provide the optical font size, and the tracking and leading is calculated for you to produce the best results. + Learn about Dynamic Metrics —> +

-

How much does it cost?

-

- Inter UI is a free and open source font family. You are free to use this font in almost any way imaginable. - Refer to the SIL Open Font License 1.1 for exact details on what the conditions and restrictions are. -

+

 

-
+

How much does it cost?

+

+ Inter UI is a free and open source font family. You are free to use this font in almost any way imaginable. + Refer to the SIL Open Font License 1.1 for exact details on what the conditions and restrictions are. +

-
-

- There are currently four weights -

- -

Features

- - -

Contextual alternates (calt)

- - DisabledEnabled - 12:34, FEX12:34, FE—X - 4.24.2 - SFO -> STOSFO -> STO - IIA —> OGGIIA —> OGG - M@N m@nM@N m@n - -
+
- -

Tabular numbers (tnum)

- - DisabledEnabled - 12345678901234567890 - 1131711 1131711  - 0040900 0040900  - 11:31,711 11:31,711  - 00:40.900 00:40.900  - -
+
+

+ There are currently four weights +

+ +

Features

+ + +

Contextual alternates (calt)

+ + DisabledEnabled + 12:34, FEX12:34, FE—X + 4.24.2 + SFO -> STOSFO -> STO + IIA —> OGGIIA —> OGG + M@N m@nM@N m@n + +
- -

Slashed zero (zero)

- - DisabledEnabled - 01230123 - -
+ +

Tabular numbers (tnum)

+ + DisabledEnabled + 12345678901234567890 + 1131711 1131711  + 0040900 0040900  + 11:31,711 11:31,711  + 00:40.900 00:40.900  + +
- -

Fractions (frac)

- - DisabledEnabled - - 1/3 22/9 3/4/5 - 1/3 22/9 3/4/5 - - -
+ +

Slashed zero (zero)

+ + DisabledEnabled + 01230123 + +
- -

Stylistic set 1: Alternate digits (ss01)

- - DisabledEnabled - - 1234567890 - 1234567890 - - 11 - 44 - 66 - 99 - -
+ +

Fractions (frac)

+ + DisabledEnabled + + 1/3 22/9 3/4/5 + 1/3 22/9 3/4/5 + + +
- -

Case alternates (case)

- - DisabledEnabled - - (Hello) [World] {9000} - (Hello) [World] {9000} - - SCHOOL @ RUNSCHOOL @ RUN - 3 + 9 = 12 * 13 + 9 = 12 * 1 - * + ÷ ± × = * + ÷ ± × = ≠ • - - :→ ← ⟶ ⟵ − - – — : - -
+ +

Stylistic set 1: Alternate digits (ss01)

+ + DisabledEnabled + + 1234567890 + 1234567890 + + 11 + 44 + 66 + 99 + +
-
+ +

Case alternates (case)

+ + DisabledEnabled + + (Hello) [World] {9000} + (Hello) [World] {9000} + + SCHOOL @ RUNSCHOOL @ RUN + 3 + 9 = 12 * 13 + 9 = 12 * 1 + * + ÷ ± × = * + ÷ ± × = ≠ • + - :→ ← ⟶ ⟵ − - – — : + +
-

- Also includes some - Localized Forms (locl), - Numerators (numr) and - Denominators (dnom). -

+ -

 

+

+ Also includes some + Localized Forms (locl), + Numerators (numr) and + Denominators (dnom). +

- -
+

 

-
+ +
-
-

The story behind Inter UI

-

- 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. -

-

- 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 - mono-spaced appearance, - making it really easy to read numbers, punctuation and very short - words, but eye-straining to read anything longer. -

-

- 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 - Figma—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback. -

+
-

 

+
+

The story behind Inter UI

+

+ 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. +

+

+ 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 + mono-spaced appearance, + making it really easy to read numbers, punctuation and very short + words, but eye-straining to read anything longer. +

+

+ 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 + Figma—where the author of Inter UI works as a designer—and slowly improved upon based on experience and feedback. +

-

Current status & usability

-

- 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 - contributions are warmly welcomed. The playground contains a lot of samples, including some common non English-language words in the playground. -

+

 

-

- Please refer to the glyph repertoire - for an overview of currently-available glyphs and their quality. -

+

Current status & usability

+

+ 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 + contributions are warmly welcomed. The playground contains a lot of samples, including some common non English-language words in the playground. +

-

 

+

+ Please refer to the glyph repertoire + for an overview of currently-available glyphs and their quality. +

-

FAQ

-
    +

     

    -
  • - How do I enable and disable font features? -
  • -
  • - In web browsers you'll want to use - font-feature-settings. - In Figma you can access features via the - Advanced Typography panel. - In Illustrator, Photoshop and friends, you can access features via the - Characters and OpenType panels. - Sketch doesn't provide a UI for configuring font features, but there's - a workaround using macOS's native font UI. -
  • +

    FAQ

    +
      -
    • - What is the difference between "unhinted" and "hinted" font files? -
    • -
    • - The font files in the "hinted" folders have additional data in them - for assisting - ClearType, - 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 - and 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. - - This article explains hinting at a greater length. -
    • +
    • + How do I enable and disable font features? +
    • +
    • + In web browsers you'll want to use + font-feature-settings. + In Figma you can access features via the + Advanced Typography panel. + In Illustrator, Photoshop and friends, you can access features via the + Characters and OpenType panels. + Sketch doesn't provide a UI for configuring font features, but there's + a workaround using macOS's native font UI. +
    • + +
    • + What is the difference between "unhinted" and "hinted" font files? +
    • +
    • + The font files in the "hinted" folders have additional data in them + for assisting + ClearType, + 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 + and 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. + + This article explains hinting at a greater length. +
    • -
    • - How reliable are the fonts served from rsms.me/inter? Is it on a CDN? -
    • -
    • - rsms.me/inter is backed by GitHub's server network and distributed - globally on the CloudFlare CDN, making usage of - https://rsms.me/inter/inter-ui.css and associated font - files very reliable and fast throughout the world. -
    • +
    • + How reliable are the fonts served from rsms.me/inter? Is it on a CDN? +
    • +
    • + rsms.me/inter is backed by GitHub's server network and distributed + globally on the CloudFlare CDN, making usage of + https://rsms.me/inter/inter-ui.css and associated font + files very reliable and fast throughout the world. +
    • -
    • - Can I help with improving Inter UI? -
    • -
    • - 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 - are freely available 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 "Contributing" document 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. -
    • +
    • + Can I help with improving Inter UI? +
    • +
    • + 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 + are freely available 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 "Contributing" document 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. +
    • -
    • - This website claims work started in 2016, but the git repository's log says it started later? -
    • -
    • - 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 - 2 990 150 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?  :—) -
    • +
    • + This website claims work started in 2016, but the git repository's log says it started later? +
    • +
    • + 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 + 2 990 150 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?  :—) +
    • -
    • - I've made a cool thing that uses Inter UI, can I share it with you? -  or -
    • -
    • - I have a different question -
    • -
    • - Reach out on Twitter (@rsms) or over email -
    • +
    • + I've made a cool thing that uses Inter UI, can I share it with you? +  or +
    • +
    • + I have a different question +
    • +
    • + Reach out on Twitter (@rsms) or over email +
    • -
    +
-
+
-
- — @rsms -
+
+ — @rsms +
- - - - +})(); 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):0g){ -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]=(3a;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 similarity index 87% rename from docs/index.css rename to 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 +// +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 similarity index 77% rename from docs/samples/bindings.js rename to 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 similarity index 100% rename from docs/favicon.png rename to docs/res/favicon.png 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 @@ - - - - - Inter UI font family - - - - - - - - - - - - - - - - - - - - - - - - - - +

+ + + + + + + + + + + + + + + + + +

+

+ Open these samples in Figma +

+ - - - - - +})(); 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=(',', ':'))