googlefonts / axisregistry

A Python API to access data from the Google Fonts variable fonts Axis Registry.
Apache License 2.0
27 stars 11 forks source link

Add Contrast Axis #3

Open felipesanches opened 2 years ago

felipesanches commented 2 years ago

Fonts to be onboarded that have this axis:


@yanone originally posted this at https://github.com/google/fonts/issues/4355:


I'm proposing the inclusion of a "contrast" axis (CNTR) into the axis registry. https://github.com/tallchai/akshar-type has one, that I’m currently onboarding.

tag: "CNTR"
display_name: "Contrast"
min_value: 0.0
default_value: 0.0
max_value: 100.0
precision: 1
fallback {
  name: "Low"
  value: 0.0
}
fallback {
  name: "High"
  value: 100.0
}
description:
  "Stroke contrast describes the stroke width difference"
  " between the thick and thin parts of a pen stroke."
  " Traditionally, a Redis pen nib would yield a low contrast stroke"
  " (monolinear) while a broad nib or pointed nib pen would"
  " yield a high contrast stroke."
Bildschirmfoto 2022-03-09 um 17 02 53 Bildschirmfoto 2022-03-09 um 17 03 02

cc @m4rc1e @davelab6 @rsheeter

davelab6 commented 2 years ago

@rsheeter asked how this related to the opaque (YOPQ, XOPQ) parametric axes by @dberlow, and I responded:

One of the key idea of parametric axes is that they are "deconstructions" or "isolated forms", and are intended to be used in concert just as much as by themselves, to "construct" desired forms; when 2+ axes are used at once, the result is a "blending" (to use an oil painting metaphor).

Since we lack the long-promised and behdad-hasn't-delivered avar2 table, blending isn't as precise as it ought to be, limiting but not negating the utility of blending parametric axes. Therefore it is convenient to offer "pre-blended" axes - like weight, width, optical size, and grade.

So a "contrast" axis is, like grade, fine to onboard. I am happy @Yanone has been listening to our general recommendations and his proposal is already pretty solid, I think. Yet, there's a few details to confirm, as @twardoch has said in #4 - since there are already quite a few fonts out there with similar axes, we should review them and see if there are ideas worth adopting, starting with the best 4 char axis tag string :)

felipesanches commented 2 years ago

@twardoch originally posted this at https://github.com/google/fonts/issues/4355#issuecomment-1063256184:


The Contrast axis exists by many names already, as per https://github.com/googlefonts/axisregistry/issues/4 :

cntr: 2 fonts, CONT: 5 fonts, ctrs: 1 font, CTST: 1 font, CNTR: 10 fonts

felipesanches commented 2 years ago

@twardoch originally posted this at https://github.com/google/fonts/issues/4355#issuecomment-1063323845:


I think the registered range should be from -100 to 100:

min_value: -100.0 default_value: 0.0 max_value: 100.0

The universalized meaning should be something like the "dominance of the thick parts over the thin parts, expressed in percent" or the "difference between 100% and the division between the thickness of the thin parts and the thickness of the thick parts". For example if the thin parts are 30 units and the thick parts are 230 units, the division yields 13% so the CONT value should be 100%–13% = 87.

Positive values should be used if the contrast follows the traditional contrast axis of the dominant writing system, and negative values should be used if the contrast follows the reversed contrast axis of the dominant writing system.

So 0 should stand for "no contrast", 100 should stand for "thin strokes are invisible and the contrast axis is traditional", and -100 should stand for "thin strokes are invisible and the contrast axis is reversed". This way, some design could go from fully reversed contrast to fully traditional contrast.

davelab6 commented 2 years ago

cntr: 2 fonts, ctrs: 1 font,

These are not a valid tag as MS reserved lowercase tags, but we can consider CTRS also...

CONT: 5 fonts, CTST: 1 font, CNTR: 10 fonts

but CNTR seems a clear popularity winner on a rote basis. However, without seeing what the typefaces are, what the min/def/max are, and who made them, its hard to parse further.

For @twaroch's proposed negative range, that is an improvement over Yanone's original proposal; clearly negative contrast is "a thing."

These proposals also can deal with eg Latin + Devanagari that have 2 scripts with different (inverted) contrast traditions, which is nice.

twardoch commented 2 years ago

I’ll provide examples

felipesanches commented 2 years ago

@tiroj said at https://github.com/google/fonts/issues/4355#issuecomment-1063424993:


The universalized meaning should be something like the "dominance of the thick parts over the thin parts, expressed in percent" or the "difference between 100% and the division between the thickness of the thin parts and the thickness of the thick parts". For example if the thin parts are 30 units and the thick parts are 230 units, the division yields 13% so the CONT value should be 100%–13% = 87.

I’m not sure that math would make a lot of sense to a font maker or user. I think I would favour the axis scale expressed as the percentage relationship of thin stroke to thick stroke. So in your example the value would be 13, and the contrast approaches monolinear by increasing the thickness of the thin strokes until the value reaches 100. I think most font makers will think of increasing contrast in terms of making some parts thinner, rather than in terms of making some parts thicker, and the relationship between the value and the glyph appearance is easier if thinner = smaller value.

yanone commented 2 years ago

-100 is good. Reverse contrast is definitely a thing :) Would a third fallback needed called "Reversed" for -100?

davelab6 commented 2 years ago

Yes min def max if min is not def

twardoch commented 2 years ago

I think most font makers will think of increasing contrast in terms of making some parts thinner

Yes, but the user values are not for font makers, but for users. The dominating concept in the language is that you have "no contrast" or "little contrast" (and for it the logic dictates a value close to 0), and you have "high contrast" or "lots of contrast" (so for simplicity, you’d expect something akin to a percentage, with a hypothetical "full contrast" being something around 100%). Basically, the percentage expresses "the amount of contrast" — which is a natural interpretation of what the term "contrast" means.

My proposed "formula" (1 – thin/thick, expressed as percentage) is compatible with the linguistic interpretation, plus it still offers a solution for universalization. And the reversed vs. traditional approach takes care of actual cases, and is world-ready.

twardoch commented 2 years ago

For width, the spec says:

"Percentage of normal width is a comparitive scale that will depend on the specific items being compared. The width of a line of text very much depends on the content of the text. No specific reference string is specified here as the basis for comparisons; a font designer can choose what they consider to be representative strings assigning a 'wdth' value to a design variant. Ideally, the 'wdth' value should provide a good estimate for most strings in the target languages of how the width of the string formatted with that 'wdth' variant compares to the width of the same string when formatted with the “normal” variant."

Without avar2, it’s not possible to do width axis that is sensible across optical size, for example. Roboto Flex rightly varies much more in width in the high opsz, but varies much less in the low opsz. So to pick the right width scale, the vendor needs to make some compromise.

The same would be true for contrast. To provide a contrast scale in a multi-axis font, the vendor should use the stroke thickness proportions of the instance that the vendor considers the primary use case.

It’s not sensible / possible to provide fool-proof mandate on the universal scale for contrast, but I still think it’s reasonable to provide sensible directional guidance.

twardoch commented 2 years ago

Then the software engineers developed wording for the OT spec, they originally always thought about some neat numeric stuff. This was true for PANOSE, for OS/2.usWidthClass, and to some extent for the descriptions of the var axes like wdth. In case of wdth, they fortunately added some softening language, though still not enough. It’s clear that cases like "the visual scale of width changes as opsz changes" were not really considered, or perhaps were dismissed as "exotic ideas". But they’re at the core of type design.

Overall, I’m not a great friend of "universal scales" that are based on strict measuring. But on the other hand, vendors like some guidance, and contrast is common enough that some common interpretation of the numbers would be desirable — just so that the implementations don’t differ wildly. They will differ if we don’t provide guidance. So the "simple" interpretation is to go from optionally -100 via 0 to 100 and see this is just a "percentage" (0 is "low", 100 is "high") within your own design, but the slightly smarter scale is along the lines I proposed — so -100 and 100 are "objectively extreme" contrasts, while values in-between are based on simple measuring (1 – thin/thick as percentage, based on a "most representative" instance of the design, with the font vendor having freedom to pick how they choose the most representative thing).

The most representative thing does not have to be "Regular". The vendor should have some freedom there. For example a vendor may have developed a high optical size first (think Playfair Display) and if there were a contrast axis, the vendor could use that high opsz to base the scale — also because the contrast typically varies most and is largest at high opsz. And then, if the vendor adds lower opsz (as is happening with Playfair), the scale would be propagated. This is the compromise, because without avar2 it’s not really possible to do differently.

twardoch commented 2 years ago

Re YOPQ and XOPQ — the parametric axes are used for synthesizing certain typographic effects by combining values on them. They’re intended for advanced users, and David Berlow’s idea is also that they ultimately may be hidden from the end-user UIs. The *OPQ axes are specifically tied to purely-vertical and purely-horizontal contrast.

The CNTR axis is intended for end-users, and provides an intuitive scale that is universal to some extent, so switching or mixing fonts at the same contrast axis value would produce comparable results. It is up to the designer to decide where exactly the typographic contrast varies — this may be horizontal strokes in some letters, vertical strokes in other letters, and diagonal strokes in yet other letters. The proposal takes into account the notion of "traditional" contrast for a given writing system.

For example, in Latin fonts, the so-called "old-style" serif fonts typically have contrast that falls diagonally. In the letter "O", the thinnest parts are in the top-left and the bottom-right "corners". "Modern" serif fonts have contrast that increases horizontally, so the thinnest parts are in the top and bottom. But in Arabic, the traditional contrast is such that the thinnest parts are on the let and right, and the thickness increases vertically. This has to do with the way calligraphers traditionally hold a flat writing tool.

If a font increases contrast in the direction that is compatible with the traditional notion of contrast for a given writing system, the CNTR axis value increases from 0 up to 100. But if the font increases contrast in the "reversed" direction, the axis value changes towards -100.

dberlow commented 2 years ago

@rsheeter asked how this related to the opaque (YOPQ, XOPQ) parametric axes?

The combination of Y and X OPQ controls the thick/thin relationship of stems in all glyphs that contain a variation in that relationship. Every single part of all the letters in "HOVER" and ``craftwork" change via one or the other OPQ. if there is any contrast anywhere in the design-space. So, first off, when @twardoch writes: “The OPQ axes are specifically tied to purely-vertical and purely-horizontal contrast.” This is incorrect, has never been so. RobotoFlex is an example one can have looked at for proof over the past 3-4 years.

However, the *OPQs of RobotoFlex and of Amstelvar would be converted differently related to use of an axis for little changes to contrast, vs use of an axis for big changes to contrast. The difference between the intended use of GRAD and the much tweeted use of "Uniwidth" defines a parallel to this issue pretty well. A GRAD axis is intended to work well within the reasonable range of the letter spacing and Kerning pairs, i.e use in small amounts. Uniwidth tries to represent a change of wght, and so has limits on how far it can vary using only the letter spacing and Kerning pairs of the default. So Uniwidth can become typographically stupid fast, and tracking doesn't help. GRAD is there to return the wght to what was specified bif it is not displaying correctly.

*OPQ in general were developed for blending other axes, including opsz, slnt, wght and wdth, and now they hide out waiting for small changes. CTST is intended as a stand-alone axis with unlimited range that should complement and not interfere with any other axes, and universally apply to the world script.

But it's not so simple even in Latin to give a blanket answer to what the change from a pair of OPQ to one CSTS means without examples…

If CTST is accepted, for the User-Friendliness of the name, in Amstelvar:

  1. YOPQ max source would be copied and renamed to CTST max.

  2. YOPQ min source would be copied and renamed to CTST min.

  3. The XOPQ min and max would be used in CTST instead of YOPQ, if;

a. the original contrast was reversed, or if

b. the font contained Arabic .e.g. as that script's CTST would need to use XOPQ duplicated as CTST min and max.

If CTST is accepted, in RobotoFlex:

  1. YOPQ max source would be copied and renamed to CTST max, then it would be re-spaced and re-kerned, because a full range of y-stem thinning in that sans would be wrong and require re-spacing and re-kerning glyphs like "ELV", where significant change to the optical appearance of one side, has not occured on the other side.

  2. YOPQ min's source would be copied and renamed to CTST min, then it would be re-spaced and re-kerned as well, or maybe even more, as more Latin users would be expected to use it.

  3. The XOPQ min and max would be used again instead for the reverse contrast scripts included in a font.

I hope that's clear, and contained in there is that some scripts/styles will require changes to advance widths and kerning under the influence of contrast variations.

So, the OPQ pair covers the universe of possible origin contrasts, and all possible changes to any relationships in contrast, truely, for all scripts, all styles, all glyphs with contrasting parts. And the intent of OPQ use now, is to make small changes. We think this is fine as it is, for visual or programmed changes to fonts with opsz already containing the recommended contrast variations by default, but seeking tweeks.

On Thu, Mar 10, 2022 at 3:11 AM Adam Twardoch @.***> wrote:

Re YOPQ and XOPQ — the parametric axes are used for synthesizing certain typographic effects by combining values on them. They’re intended for advanced users, and David Berlow’s idea is also that they ultimately may be hidden from the end-user UIs. The *OPQ axes are specifically tied to purely-vertical and purely-horizontal contrast.

The CNTR axis is intended for end-users, and provides an intuitive scale that is universal to some extent, so switching or mixing fonts at the same contrast axis value would produce comparable results. It is up to the designer to decide where exactly the typographic contrast varies — this may be horizontal strokes in some letters, vertical strokes in other letters, and diagonal strokes in yet other letters. The proposal takes into account the notion of "traditional" contrast for a given writing system.

For example, in Latin fonts, the so-called "old-style" serif fonts typically have contrast that falls diagonally. In the letter "O", the thinnest parts are in the top-left and the bottom-right "corners". "Modern" serif fonts have contrast that increases horizontally, so the thinnest parts are in the top and bottom. But in Arabic, the traditional contrast is such that the thinnest parts are on the let and right, and the thickness increases vertically. This has to do with the way calligraphers traditionally hold a flat writing tool.

If a font increases contrast in the direction that is compatible with the traditional notion of contrast for a given writing system, the CNTR axis value increases from 0 up to 100. But if the font increases contrast in the "reversed" direction, the axis value changes towards -100.

— Reply to this email directly, view it on GitHub https://github.com/googlefonts/axisregistry/issues/3#issuecomment-1063774666, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAO5VDTYKQBWGZTSCORGPCDU7GVBRANCNFSM5QKEMDQQ . You are receiving this because you were mentioned.Message ID: @.***>

davelab6 commented 2 years ago

There are 3 general benefits to variable fonts, to compress, to express, to finesse.

To me there's a clear distinction between parametric opaque axes and a contrast axis; the former are to finesse and the latter is to express. Similarly as @dberlow says, grade is to finesse and uniwidth is to express.

A contrast axis blends changes in both X and Y dimensions even more than parametric opaque axes do; XOPQ mainly focuses on the X dimension and YOPQ mainly focuses on the Y dimension, their main focus is what makes them essentially parametric; a single OPQ axis would inherently not be a parametric axis, since it isn't isolating a parameter.

The benefit for end users of such a single blend is its context of use for expressivity. I don't really see this as different to expressive weight or width axes on os/2 class value ranges; ideally (perhaps gated on an avar2 table) we could have fonts built without those axes and only parametric axes and recipes to use them in concert to access the styles that are available in fonts built with os2 axes.

But for now, we have fonts without parametric axes that are pre-blended, and that's OK.

yanone commented 2 years ago

But in Arabic, the traditional contrast is such that the thinnest parts are on the let and right, and the thickness increases vertically. This has to do with the way calligraphers traditionally hold a flat writing tool.

For the sake of smart-assing, I need to correct this: Arabs and everyone else hold the pen the same way. But the Arabic broad nib reed pens were cut at an angle inverse to the Latin reed pens (or, possibly, Latin pens where cut straight). If you hold the below pen in the correct way, it produces a horizontal-emphasis stroke. I could only find pictures that show pens from underneath, so imagine it mirrored.

6043a098f4bb4da20672aa32_DSC00126

To add to the actual discussion, or rather, confirm what's been said: We need -100 to 100 range for this axis, and 100 should yield a contrast axis that's the dominant one for each font’s dominant writing script. Meaning: The contrast for Arabic and Latin is typically inverse as we've discussed, but both cases should carry positive CNTR values.

tallchai commented 1 year ago

Hi, checking if there is an update on this. It's been open since a year.

dberlow commented 1 year ago

My thoughts.

In calligraphic fonts, as well as any font with contrast, it is fine with me if XOPQ is the long side of the tool, YOPQ is the short side of the tool, and whatever angle that tool is held at, the marks of the form left by the short end, are YOPQ, and those left by the long side are XOPQ, and the stuff in between is in the hands of the tool holder.

Contrast is an axis where the value perplexes me because contrast is by definition two values. So while an axis can control it, its relationship of values, slider and visual effect can only be understood visually, i.e. by looking at it.

Within this issue, I have seen a handful of variable fonts so far, that just change the contrast and nothing else, and label it as either optical size or contrast.

Sorry if thi On Mar 8, 2023, at 6:34 PM, tallchai @.***> wrote:

 Hi, checking if there is an update on this. It's been open since a year.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.

tiroj commented 1 year ago

In calligraphic fonts, as well as any font with contrast, it is fine with me if XOPQ is the long side of the tool, YOPQ is the short side of the tool, and whatever angle that tool is held at, the marks of the form left by the short end, are YOPQ, and those left by the long side are XOPQ, and the stuff in between is in the hands of the tool holder.

To be sure I understand correctly: are you saying that in ‘any font with contrast’ the meaning of XOPQ and YOPQ is disassociated from X,Y directionality, and instead reflects the dynamics of a notional writing tool as applied to different scripts? So ‘X’ is always whatever is conventionally heaviest, and ‘Y’ is always what is conventionally thinnest?