Giter Club home page Giter Club logo

wavefont's Introduction

wavefont build

A typeface for rendering vertical bars data: waveforms, spectrums, diagrams, histograms, columns etc.

Playground  •  Google fonts  •  V-fonts  •   Wavearea

Usage

Place Wavefont[ROND,YELA,wght].woff2 into your project directory and use this code:

<style>
@font-face {
	font-family: wavefont;
	font-display: block;
	src: url(./Wavefont[ROND,YELA,wght].woff2) format('woff2');
}
.wavefont {
	--wght: 400;
	font-family: wavefont;
	font-variation-settings: 'wght' var(--wght), 'ROND' 30, 'YELA' 0;
}
</style>

<!-- Set values manually -->
<textarea id="waveform" class="wavefont" cols="100">
abcdefghijklmnopqrstuvwwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
</textarea>

<script>
// Set values programmatically (more precise)
waveform.textContent = Array.from({length: 100}, (_,i) => String.fromCharCode(0x100 + i)).join('')
</script>

Ranges

Wavefont bars correspond to values from 0 to 100, assigned to different characters:

  • 0-9 chars are for simplified manual input with step 10 (bar height = number).
  • a-zA-Z for manual input with step 2, softened at edges a and Z (bar height = number of letter).
  • U+0100-017F for 0..127 values with step 1 (char = String.fromCharCode(0x100 + value)).

Variable axes

Tag Range Default Meaning
wght 1-1000 400 Bar width, or boldness.
ROND 0-100 100 Border radius, or roundness (percent).
YELA -100-100 -100 Alignment: bottom, center or top.

To adjust axes via CSS:

.wavefont {
  font-variation-settings: 'wght' var(--wght, 40), 'ROND' var(--rond, 0), 'YELA' var(--align, 0);
  letter-spacing: 1ch; /* 1ch unit === 1 bar width */
}

Features

  • Ranges, values and width is compatible with linefont, so fonts can be switched preserving visual coherency.
  • Visible charcodes fall under marking characters unicode category, ie. recognized as word by regexp and can be selected with Ctrl + or double click. Eg. waveform segments separated by or - are selectable by double click.
  • Characters outside of visible ranges are clipped to 0, eg. , \t etc.
  • -–._* map to 1 value, | maps to max value, ▁▂▃▄▅▆▇█ map to corresponding bars.
  • Accent acute  ́ (U+0301) shifts bar 1-step up, circumflex accent  ̂ (U+0302) 10-steps up. Eg. \u0101\u0302\u0302\u0301\u0301\u0301 shifts 23 steps up.
  • Accent grave  ̀ (U+0300) shifts bar 1-step down, caron  ̌ (U+030C) shifts 10 steps down, eg. \u0101\u030c\u0300\u0300\u0300 shifts 13 steps down.
  • Caret span is -20..120, so line-height = 1.4 is minimal non-overlapping selection.

JS package

Optional wavefont package exposes a function that calculates string from values for your convenience.

import wf from 'wavefont'

// get characters for values from 0..127 range
wf(0, 1, 50, 99, 127, ...) // ĀāIJţŤ...

Building

make build

See also

  • linefont − font-face for rendering linear data.

References

🕉

wavefont's People

Contributors

dependabot[bot] avatar dy avatar rosawagner avatar simoncozens avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wavefont's Issues

[better] demo

  • app-audio (-like) waveform source
  • randomize color palette button (mb slight animated color shift)
  • baseline highlight
  • download generated optimized static font (based on selected settings)
  • select unicode ranges to cover
  • #29 diverse waveforms
  • waveform player, spectrum player
  • paint waveform with pencil, to copy-paste
  • !examples: textarea-recorder, messenger message, speech recognition, proofing page (current) etc.

3.0 improvements needed

  • More up/down shifts via accents, at least till 50.
  • Latin-Ext range for Low-align, Cyrillic range for Center-align, see #21 (comment) for argumentation
  • Latin/ASCII cover 52 chars - it seems to be very natural expectation.
  • Embed last-resort blank font into wavefont to avoid CSS fallback. faster to have sync fallback and build wavefont upon it.
  • WGHT and WDTH are useful as separate properties. Unlike tracking, WDTH stabilizes advance width as absolute value, so weight can safely be changed within the allocated stride.
  • char should be left-aligned within width, not center-aligned.
  • Map axes to standardized names - SOFT.
  • ~~pass fontbakery tests #14 ~~
  • +-10 y-shift accents #19
  • expose meaningful JS API
  • ~~demo with painter #27 ~~
  • Limit weight to 400 (no sense to have it too big, besides that's standard value for Google Fonts).

Alias characters / unicode subranges

Originally posted by @dy in adobe-type-tools/afdko#1308 (comment)

Provide alias characters in

  1. Private use area, for generally main correct use, then font can be extended up to 1000 values
  2. 0-9, for manual use
  3. a-z maybe, for extended manual use
  4. Cyrillic range for 255 values
  5. Stub all spaces, tabs, newlines
  6. Use 1-value for space character instead of 0

Fix tall-characters hinting

image

I mean it looks nice with this waveform, but the way to fix it is:

  • convert resulting ttf to ufo
  • apply good hinting from normal glyphs to tall glyphs
  • regenerate hoping that ufo can define hinting

Optimize performance

Think up ideas to optimize performance, drastically. Maybe ttf may help.
In the meantime, do iphone dictaphone use-case and see if it is enough.

Expand 0..100 to 0..127

+ 0..100 is human range and is kind of covered by a-Z values
+ 0..128 is programmatic range and it anyways starts with hex number - impossible for human to remember
+ 28 doesn't add extra weight
+ 128 better matches programmatic values eg. uint8/PCM range with 256 values
+ 128 is needed for midifont
- even 256 values are available, although that can be problematic for linefont, besides midifont needs only 128
+ it is available in latin range
- a bit of trouble aligning a-Z to 128 range: the step is 2.46
+ user can artificially limit values to 0..100, 28 can be considered extra clipping (that is, for audio signals)

2.0

  • variable axis: width #15 via designfile
  • feature-file with GPOS 8 positioning marks #2
  • ~~proper hints without subpixel gaps (psautohint?) #3 ~~ impossible
  • all checks passed
  • windows-able to install/use #13
  • proper handling of clipping #7
  • better demo

Add quality variants

We don't need that densed font for the data at hand. Guess bold version should work.

2.2

  • stuff all spaces (non-marking characters)
  • CSS unicode subranges 0..1, 0..100, 0..1000, full - large or small fonts are discarded in favor of one font version
  • .-−— replace with 1
  • ▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▐░▒▓▔▕ & vertical bars
  • stuff clipping (values a bit outside of range)
  • better contrast (1:1000)?
  • amplitude axis? that would multiply number of masters without apparent profit
  • better plopfile

Non-marking characters:

Character name | Unicode | Description
-- | -- | --
&Tab; | 00009 | tabulator stop; horizontal tabulation
&NewLine; | 0000A | force a line break; line feed
&Space; | 00020 | one em of space in the current font
&NonBreakingSpace; | 000A0 | space that is not a legal breakpoint
&ZeroWidthSpace; | 0200B | space of no width at all
&VeryThinSpace; | 0200A | space of width 1/18 em
&ThinSpace; | 02009 | space of width 3/18 em
&MediumSpace; | 02005 | space of width 4/18 em
&ThickSpace; | 02005-0200A | space of width 5/18 em
&NegativeVeryThinSpace; | 0200A-02063 | space of width -1/18 em
&NegativeThinSpace; | 02009-02063 | space of width -3/18 em
&NegativeMediumSpace; | 0205F-02063 | space of width -4/18 em
&NegativeThickSpace; | 02005-02063 | space of width -5/18 em
&InvisibleTimes; | 02062 | marks multiplication when it is understood without a mark (Section 3.2.4 [Operator, Fence, Separator or Accent (mo)]
&ApplyFunction; | 02061 | character showing function application in presentation tagging (Section 3.2.4 [Operator, Fence, Separator or Accent (mo)]

Missing copyright notice

Just found out name ID 0 is missing, and the copyright notice was added in place of the Trademark (name ID 7)

v4 improvements

  • marking/unmarking space? It seems practically signal is always marked as something, even silence. 0 signal is not the same as absence of signal. tough to decide - there's no obvious alternative for spacer.
  • instead maybe make 0 value actually 1 value. not helpful to anything
  • Shorter offshoot / line-height? Wavearea shows too broad line-height. 1.2 value would be better. - just use 128 range
  • Rename axis to yaln

Remove wdth axis

  • saves 30kb to file size
  • avoids conflict with google axis limits 50..200
  • external letter-spacing can be arbitrary/unlimited, unlike font axis, so that can be unavoidable anyways
  • external letter-spacing has better units via ch: either 1ch = 1bar

Design space to match GF

Hi @dy I am looking at the UFOs, and I am a bit afraid of changing the design space values without breaking all your settings, so maybe you can do it?

We would need the axes to be in that order and these values:

<axis default="0" minimum="0" maximum="100" name="Roundness" tag="ROND"/>
<axis default="100" minimum="50" maximum="200" name="Width" tag="wdth"/>
<axis default="400" minimum="100" maximum="900" name="Weight" tag="wght"/>

cf https://googlefonts.github.io/gf-guide/variable.html#most-common-axes

The default instance of the font (master origin) should be named "Wavefont Regular" (0, 100, 400). So kind of in the middle in terms of weight and width, so users can see the shapes without having to move a slider. Step by step we'll make it ^^

Style variations: caps-only, no-caps

At some resolutions it may be meaningful to display only relative caps (ends of bars), not full bars.
Stylistic alternatives can come handy here.
But features must define proper replacements then, eg. (mark?) combination of bar & cap.

Value encoding strategy

What would be the right strategy to map characters?

0. Direct mapping to char codes with offset

  • Super-simple uints.map(v => String.fromCharCode(v + offset))
  • Easy to remember/understand
  • Extendable as baseline shift (I guess? GPOS type 9 via comb characters?)
  • Friendlier to variable font for align axis
  • Good offsets for 255 characters: U+A000, U+1500, U+1E00, U+A500, U+AC00 (~0x1fff!), U+E000 (private, but not selectable)

1. Hex pairs (doubles) as a0a1a2

  • Trivial encoding: uints.map(v => v.toString(16)).join('')
  • Deleting first character rerenders full font, non-pair copying doesn't make sense
  • Ligatures don't seem to support LigatureCaret and ligature width is equally split
  • Doesn't seem to be possible to collapse one of the characters if they're normal
    ~ Only using combining accents make full-length ligatures

2. a-z as main values, 0-9 as fraction (0-width), or any other separation on base and fract

  • No ligatures problem, selection is resolved: second char is simply 0-width like combining mark
    ~ Deletion still problematic, but not as much as the first option
  • Encoding is not as trivial: uints.map(v => Math.floor(v) + '\u0300'.repeat(v%1)) etc.
  • Manually understandable: a0, b3, g9

3. 0-9 as main values, ↑ and ↓ as combining modifiers

~ similar to previous conceptually

  • Selection is good
  • Deletion is as good as combining characters
    ~ Manually not simple to type, but readable
  • Precision control via eg. number of combining characters, eg. 0̂9̂̂̂5̂̂̂̂̂̂̂ → 0.1, 9.3, 5.7 etc.
  • Encoding is zoom-dependent, from as simple as uints.map(v => Math.floor(v)) to zoom control.
    ~ 0̂̂̂̂̂̂̂̂̂̂ === 1, latin arithmetic-like system

4. Baseless modifiers only .̂̂̂̂.̬̬̬.̬̬.̬̬̬̬̬̬̬.̬.̬̬̬̬̬̬̬̬̬̬̬̬̬.̂̂̂.̂̂̂̂̂̂̂.̂̂̂̂̂̂̂̂̂̂.̂̂̂.̂̂̂̂.̂̂̂̂̂.̂̂.̂

~ Printer-like tech.
~ With vertical space combining mark enables xy-plot as a single string...
~ Would require sort of i,d,v,x composing characters to combine into bar

5. First value is chunk identifier (latin), rest is spaces with combining marks

  • Dbl-click selection at least in browsers, selects word and all space after it.
  • "Space" has literal meaning of "move caret right without print"
  • Character more semantically acts as identifier in case of font fallback, which is a good mathematical/data practice (legend etc)
  • Encoding requires heuristic: marking a chunk, then defining spaces
  • Dblclicking space after id doesn't select an id

y-shift encoding strategy

Values are chosen to be direct positive values from 0-100 range from U+0100 unicode range. No negatives.
What would be the right approach to shift? Factors:

  • align: center feature may require negative shift
  • editing not affect parts outside of selected fragment
  • zoom levels - should clutter text with multiple shift symbols

0. Absolute shift

  • Just a bit unusual in editing, since requires guaranteed 1 extra operation per sample, worse than 1. on large scale since relative offset reduces shifts to minimum

1. Cursive + 1 up/down

  • Natural flow (only up/down is needed),
  • reduces number of characters in a font (only up/down needed)
  • reduces number of characters in textarea (no need to provide each character level)
  • removes clipping limit - waveform can go as high/low as required.
  • editing combinings is a bit unusual - cutting a character removes shift of the following character and all subsequents baseline shift.
  • separate up/down character is better than combinings: it makes step "up" by typing it (muscular logic). It can also be visualized as thin connection line. But still redundant and a bit unexpected direction change in editing, 0-width space eats away one..n caret shifts
  • Relative positioning creates a lot of noise on small scales when there's too much vertical variation, like 9,0,9,0,9,0. Absolute values are guaranteed to limit to one extra character overhead.

2. Cursive + n up/down

A mix of 0. and 1.: relative offsets to any amount.

  • Removes small scale clutter, reducing number of shifts to 1
  • still has critical baseline shift drawback
  • requires 2x shifting characters: up 100, down 100

2.1 Cursive with copy-paste compensation

  • can fix critical baseline shift

3. A separate font for sample values (caps-only, or like linefont)

Since bars are almost always 0-aligned, with little decorative shifts up/down, that hardly affects baseline shift (can be handled on copy/paste events); and samples data doesn't need full bar value, but rather single point with nice shift ability, mb there's a sense switching from bars font to samples font for small-scale cases.

That samples font would be just timedata font with features:

  • use any symbol/character
  • shift subsequent absolute markers (combining?) or mb provide shifted characters already for better editing
  • no need for center-align => no need for negative shifts/values
  • it can be even be a linear-data font, connecting chars with proper lines _/ˉ_/ˉ
  • width, weight variables

Originally posted by @dy in #18 (comment)

Add ttf version

For generic fonts it is better.
Possible strategies:

  • otf2ttf
  • opentype to svgPath to ttf

Cap-component version artifact

image
width: 5, size: 48px
It also happens on other sizes with TTF font.
Considering that

  • font file size is bigger with caps
  • excluding glyphs from interpolation is impossible
  • number of masters doesn't decrease
    maybe it's worthwhile sticking to just radius version

ALGN axis vs cyrillic range for centered values

+ Both of cyrillic/latin have nice offets (0x100, 0x400)
+ Offsets start with sequence of word 100 characters
+ Give intuition of centered or low-bound values by C or L range names.
+ It saves font size (somewhat)
+ Languages sort-of use same pattern: Lowcase/upcase glyph with same original char
+ Latin-ext is compatible with wavefont v2.
- Data needs to be converted from 0x100 to 0x400 to be displayed under different alignment. (Sort of toUpperCase).

? Is there a case when both centered and lower bound alignment is needed?

  • Mixing waveform with spectrogram in a single line?
  • Preloaders animation (binance).

? Is there a case when we need to convert from one case to another?

? Is there a case when top or intermediate alignment is needed?

  • Preloaders animation (binance).

Interpolation problems in `Wavefont[ROND,YELA,wght].ttf`

Hello!

This is an automatically-generated report about possible interpolation problems in Wavefont[ROND,YELA,wght].ttf, as found in the Google Fonts catalog.

The particular version of the font that was tested was archive:.

To download a PDF version of this report with helpful visuals of the problems, click here; Or to view it on the GitHub website, click here.

The report follows:

Glyph _1 was not compatible:
  Masters: '', 'ROND=0.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'ROND=0.0'
  Masters: '', 'wght=4.0':
    Contour order differs: [0, 1, 2] in '', [2, 0, 1] in 'wght=4.0'
  Masters: 'YELA=100.0', 'YELA=100.0 wght=4.0':
    Contour order differs: [0, 1, 2] in 'YELA=100.0', [2, 0, 1] in 'YELA=100.0 wght=4.0'
Glyph _1.clip was not compatible:
  Masters: '', 'wght=4.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=4.0'; reversed: True
Glyph _10 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _10.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _11 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _11.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _12 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _12.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _13 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _13.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _14 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _14.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _15 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _15.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _16 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _16.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _17 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _17.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _18 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _18.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
Glyph _19 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _19.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
Glyph _2 was not compatible:
  Masters: '', 'ROND=0.0':
    Contour order differs: [0, 1, 2] in '', [2, 0, 1] in 'ROND=0.0'
  Masters: '', 'wght=4.0':
    Contour order differs: [0, 1, 2] in '', [2, 0, 1] in 'wght=4.0'
Glyph _20 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _20.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
Glyph _21 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _21.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
Glyph _22 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _22.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 27 in 'ROND=0.0'; reversed: True
Glyph _23 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _23.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 27 in 'ROND=0.0'; reversed: True
Glyph _24 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _24.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 27 in 'ROND=0.0'; reversed: True
Glyph _25 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 0, 2] in 'wght=1000.0'
Glyph _26 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _27 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _28 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _29 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _3 was not compatible:
  Masters: '', 'ROND=0.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'ROND=0.0'
  Masters: '', 'wght=4.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=4.0'
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 3 in 'wght=1000.0'; reversed: True
Glyph _3.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
Glyph _30 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _31 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _32 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _33 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _34 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _35 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _36 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [2, 1, 0] in 'wght=1000.0'
Glyph _4 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 3 in 'wght=1000.0'; reversed: True
Glyph _4.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _5 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 3 in 'wght=1000.0'; reversed: True
Glyph _5.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _6 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _6.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _7 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _7.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _8 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _8.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True
Glyph _9 was not compatible:
  Masters: '', 'wght=1000.0':
    Contour order differs: [0, 1, 2] in '', [1, 2, 0] in 'wght=1000.0'
Glyph _9.clip was not compatible:
  Masters: '', 'ROND=0.0':
    Contour 0 start point differs: 0 in '', 19 in 'ROND=0.0'; reversed: True
  Masters: '', 'wght=1000.0':
    Contour 0 start point differs: 0 in '', 19 in 'wght=1000.0'; reversed: True

This report was generated using the fonttools varLib.interpolatable tool. We understand that sometimes the tool generates false-positives. Particularly for more complicated font designs. If you did not find this report useful, please apologize and ignore & close it.

To give feedback about this report, please file an issue or open a discussion at fonttools.

Normalize dimensions

Ensure monospace offset, for example, 64px font-size should advance exactly 64px right for the 64 data items.

Indicate space

It may be valuable to display empty space. Selection-wise it's helpful.
Maybe a default blank (line)?

Shift-overlap glyphs strategy

Tall glyphs can be composed of 2..N smaller glyphs with overlay as components. It doesn't seem to create any antialiasing problems, but potentially can reduce font size. If masters can exclude glyphs ref - size can be reduced by axes even more.

Align with font requirements

Some requirements are defined by fontforge:

  • 1000 size instead of 256
  • glyph overshoot causing wrong subpixel AA
  • many glyph errors

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.