Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2k
Add support for numeric font weight#6990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
37dee483212866448eb803a3f45815b25a5be24a14d8424a3353efc4abb3fc88266a6d46e6b273e4942a72044b54d52885b92ef23b12539654005b909f4dd3f67b40c99162e5990fa8df3c0356a5cc7f863824c1190aef1091e7d382de3ff59779f3f6fcbd710f477f82863fdbff00ac48d057fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Add support for numeric text font `weight` [[#6990](https://github.com/plotly/plotly.js/pull/6990)] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -100,6 +100,8 @@ exports.valObjectMeta = { | ||
| requiredOpts: [], | ||
| otherOpts: ['dflt', 'min', 'max', 'arrayOk'], | ||
| coerceFunction: function(v, propOut, dflt, opts) { | ||
| if(isTypedArraySpec(v)) v = decodeTypedArraySpec(v); | ||
| if(!isNumeric(v) || | ||
| (opts.min !== undefined && v < opts.min) || | ||
| (opts.max !== undefined && v > opts.max)) { | ||
| @@ -114,8 +116,15 @@ exports.valObjectMeta = { | ||
| 'are coerced to the `dflt`.' | ||
| ].join(' '), | ||
| requiredOpts: [], | ||
| otherOpts: ['dflt', 'min', 'max', 'arrayOk'], | ||
| otherOpts: ['dflt', 'min', 'max', 'arrayOk', 'extras'], | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @archmoj Is this adding a new functionality to That's pretty cool -- is there anywhere we should document that internally? ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Makes me think, it would be awesome if we could build checking the Plotly.py codegen into the CI process. It would have to produce some kind of output that's easy to verify. It could run only if the Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps add a line in the docstring here explaining ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For flag lists combination mean something. That's why it is commented. | ||
| coerceFunction: function(v, propOut, dflt, opts) { | ||
| if((opts.extras || []).indexOf(v) !== -1) { | ||
| propOut.set(v); | ||
| return; | ||
| } | ||
| if(isTypedArraySpec(v)) v = decodeTypedArraySpec(v); | ||
archmoj marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if(v % 1 || !isNumeric(v) || | ||
| (opts.min !== undefined && v < opts.min) || | ||
| (opts.max !== undefined && v > opts.max)) { | ||
| @@ -156,6 +165,8 @@ exports.valObjectMeta = { | ||
| requiredOpts: [], | ||
| otherOpts: ['dflt', 'arrayOk'], | ||
| coerceFunction: function(v, propOut, dflt) { | ||
| if(isTypedArraySpec(v)) v = decodeTypedArraySpec(v); | ||
archmoj marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if(tinycolor(v).isValid()) propOut.set(v); | ||
| else propOut.set(dflt); | ||
| } | ||
| @@ -198,6 +209,8 @@ exports.valObjectMeta = { | ||
| requiredOpts: [], | ||
| otherOpts: ['dflt', 'arrayOk'], | ||
| coerceFunction: function(v, propOut, dflt) { | ||
| if(isTypedArraySpec(v)) v = decodeTypedArraySpec(v); | ||
archmoj marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| if(v === 'auto') propOut.set('auto'); | ||
| else if(!isNumeric(v)) propOut.set(dflt); | ||
| else propOut.set(modHalf(+v, 360)); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -190,7 +190,7 @@ function convertTextStyle(gd, trace) { | ||
| if( | ||
| isArrayOrTypedArray(tfs) || | ||
| Array.isArray(tff) || | ||
| Array.isArray(tfw) || | ||
| isArrayOrTypedArray(tfw) || | ||
| Array.isArray(tfy) || | ||
| Array.isArray(tfv) | ||
| ) { | ||
| @@ -207,7 +207,7 @@ function convertTextStyle(gd, trace) { | ||
| ) * plotGlPixelRatio; | ||
| fonti.family = Array.isArray(tff) ? tff[i] : tff; | ||
| fonti.weight = Array.isArray(tfw) ? tfw[i] : tfw; | ||
| fonti.weight = weightFallBack(isArrayOrTypedArray(tfw) ? tfw[i] : tfw); | ||
| fonti.style = Array.isArray(tfy) ? tfy[i] : tfy; | ||
| fonti.variant = Array.isArray(tfv) ? tfv[i] : tfv; | ||
| } | ||
| @@ -216,7 +216,7 @@ function convertTextStyle(gd, trace) { | ||
| optsOut.font = { | ||
| size: tfs * plotGlPixelRatio, | ||
| family: tff, | ||
| weight: tfw, | ||
| weight: weightFallBack(tfw), | ||
| ||
| style: tfy, | ||
| variant: tfv | ||
| }; | ||
| @@ -225,6 +225,14 @@ function convertTextStyle(gd, trace) { | ||
| return optsOut; | ||
| } | ||
| // scattergl rendering pipeline has limited support of numeric weight values | ||
| // Here we map the numbers to be either bold or normal. | ||
| function weightFallBack(w) { | ||
| if(w <= 1000) { | ||
| return w > 500 ? 'bold' : 'normal'; | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the threshold be 400? ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 500 is Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, ok, I guess if the only options are | ||
| } | ||
| return w; | ||
| } | ||
| function convertMarkerStyle(gd, trace) { | ||
| var count = trace._length; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| 'use strict'; | ||
| // Must use one of the following fonts as the family, else default to 'Open Sans Regular' | ||
| // See https://github.com/openmaptiles/fonts/blob/gh-pages/fontstacks.json | ||
| var supportedFonts = [ | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @archmoj Does Mapbox make their list of supported fonts public anywhere as part of their package? Just wondering if there's a way we can ensure this list is always up-to-date without updating it manually. ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No in fact we use latest v1 version of Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK got it. Do you know to what extent ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. It's a kind of problem we could address when/if we switch to it. Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @emilykl , there is a migration branch in here maplibre where we should be able to try out: | ||
| 'Metropolis Black Italic', | ||
| 'Metropolis Black', | ||
| 'Metropolis Bold Italic', | ||
| 'Metropolis Bold', | ||
| 'Metropolis Extra Bold Italic', | ||
| 'Metropolis Extra Bold', | ||
| 'Metropolis Extra Light Italic', | ||
| 'Metropolis Extra Light', | ||
| 'Metropolis Light Italic', | ||
| 'Metropolis Light', | ||
| 'Metropolis Medium Italic', | ||
| 'Metropolis Medium', | ||
| 'Metropolis Regular Italic', | ||
| 'Metropolis Regular', | ||
| 'Metropolis Semi Bold Italic', | ||
| 'Metropolis Semi Bold', | ||
| 'Metropolis Thin Italic', | ||
| 'Metropolis Thin', | ||
| 'Open Sans Bold Italic', | ||
| 'Open Sans Bold', | ||
| 'Open Sans Extrabold Italic', | ||
| 'Open Sans Extrabold', | ||
| 'Open Sans Italic', | ||
| 'Open Sans Light Italic', | ||
| 'Open Sans Light', | ||
| 'Open Sans Regular', | ||
| 'Open Sans Semibold Italic', | ||
| 'Open Sans Semibold', | ||
| 'Klokantech Noto Sans Bold', | ||
| 'Klokantech Noto Sans CJK Bold', | ||
| 'Klokantech Noto Sans CJK Regular', | ||
| 'Klokantech Noto Sans Italic', | ||
| 'Klokantech Noto Sans Regular' | ||
| ]; | ||
| module.exports = { | ||
| isSupportedFont: function(a) { | ||
| return supportedFonts.indexOf(a) !== -1; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -10,6 +10,7 @@ var Colorscale = require('../../components/colorscale'); | ||
| var Drawing = require('../../components/drawing'); | ||
| var makeBubbleSizeFn = require('../scatter/make_bubble_size_func'); | ||
| var subTypes = require('../scatter/subtypes'); | ||
| var isSupportedFont = require('./constants').isSupportedFont; | ||
| var convertTextOpts = require('../../plots/mapbox/convert_text_opts'); | ||
| var appendArrayPointValue = require('../../components/fx/helpers').appendArrayPointValue; | ||
| @@ -369,11 +370,58 @@ function arrayifyAttribute(values, step) { | ||
| function getTextFont(trace) { | ||
| var font = trace.textfont; | ||
| var str = ''; | ||
| if(font.weight === 'bold') str += ' Bold'; | ||
| if(font.style === 'italic') str += ' Italic'; | ||
| var textFont = font.family; | ||
| if(str) textFont = textFont.replace(' Regular', str); | ||
| textFont = textFont.split(', '); | ||
| var family = font.family; | ||
| var style = font.style; | ||
| var weight = font.weight; | ||
| var parts = family.split(' '); | ||
| var isItalic = parts[parts.length - 1] === 'Italic'; | ||
| if(isItalic) parts.pop(); | ||
| isItalic = isItalic || style === 'italic'; | ||
| var str = parts.join(' '); | ||
| if(weight === 'bold' && parts.indexOf('Bold') === -1) { | ||
| str += ' Bold'; | ||
| } else if(weight <= 1000) { // numeric font-weight | ||
| // See supportedFonts | ||
| if(parts[0] === 'Metropolis') { | ||
| str = 'Metropolis'; | ||
| if(weight > 850) str += ' Black'; | ||
| else if(weight > 750) str += ' Extra Bold'; | ||
| else if(weight > 650) str += ' Bold'; | ||
| else if(weight > 550) str += ' Semi Bold'; | ||
| else if(weight > 450) str += ' Medium'; | ||
| else if(weight > 350) str += ' Regular'; | ||
| else if(weight > 250) str += ' Light'; | ||
| else if(weight > 150) str += ' Extra Light'; | ||
| else str += ' Thin'; | ||
| } else if(parts.slice(0, 2).join(' ') === 'Open Sans') { | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Couldn't this be ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. That may break IE11 which is fine as of today :) | ||
| str = 'Open Sans'; | ||
| if(weight > 750) str += ' Extrabold'; | ||
| else if(weight > 650) str += ' Bold'; | ||
| else if(weight > 550) str += ' Semibold'; | ||
| else if(weight > 350) str += ' Regular'; | ||
| else str += ' Light'; | ||
| } else if(parts.slice(0, 3).join(' ') === 'Klokantech Noto Sans') { | ||
| str = 'Klokantech Noto Sans'; | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh I see, maybe not, because it has already passed through the ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. No that shouldn't happen because further down we test and ensure the font is supported. ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed in bff00ac. | ||
| if(parts[3] === 'CJK') str += ' CJK'; | ||
| str += (weight > 500) ? ' Bold' : ' Regular'; | ||
| } | ||
| } | ||
| if(isItalic) str += ' Italic'; | ||
| if(str === 'Open Sans Regular Italic') str = 'Open Sans Italic'; | ||
| else if(str === 'Open Sans Regular Bold') str = 'Open Sans Bold'; | ||
| else if(str === 'Open Sans Regular Bold Italic') str = 'Open Sans Bold Italic'; | ||
| else if(str === 'Klokantech Noto Sans Regular Italic') str = 'Klokantech Noto Sans Italic'; | ||
| // Ensure the result is a supported font | ||
| if(!isSupportedFont(str)) { | ||
| str = family; | ||
| } | ||
| var textFont = str.split(', '); | ||
| return textFont; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -8,44 +8,7 @@ var handleLineDefaults = require('../scatter/line_defaults'); | ||
| var handleTextDefaults = require('../scatter/text_defaults'); | ||
| var handleFillColorDefaults = require('../scatter/fillcolor_defaults'); | ||
| var attributes = require('./attributes'); | ||
| // Must use one of the following fonts as the family, else default to 'Open Sans Regular' | ||
| // See https://github.com/openmaptiles/fonts/blob/gh-pages/fontstacks.json | ||
| var supportedFonts = [ | ||
| 'Metropolis Black Italic', | ||
| 'Metropolis Black', | ||
| 'Metropolis Bold Italic', | ||
| 'Metropolis Bold', | ||
| 'Metropolis Extra Bold Italic', | ||
| 'Metropolis Extra Bold', | ||
| 'Metropolis Extra Light Italic', | ||
| 'Metropolis Extra Light', | ||
| 'Metropolis Light Italic', | ||
| 'Metropolis Light', | ||
| 'Metropolis Medium Italic', | ||
| 'Metropolis Medium', | ||
| 'Metropolis Regular Italic', | ||
| 'Metropolis Regular', | ||
| 'Metropolis Semi Bold Italic', | ||
| 'Metropolis Semi Bold', | ||
| 'Metropolis Thin Italic', | ||
| 'Metropolis Thin', | ||
| 'Open Sans Bold Italic', | ||
| 'Open Sans Bold', | ||
| 'Open Sans Extra Bold Italic', | ||
| 'Open Sans Extra Bold', | ||
| 'Open Sans Italic', | ||
| 'Open Sans Light Italic', | ||
| 'Open Sans Light', | ||
| 'Open Sans Regular', | ||
| 'Open Sans Semibold Italic', | ||
| 'Open Sans Semibold', | ||
| 'Klokantech Noto Sans Bold', | ||
| 'Klokantech Noto Sans CJK Bold', | ||
| 'Klokantech Noto Sans CJK Regular', | ||
| 'Klokantech Noto Sans Italic', | ||
| 'Klokantech Noto Sans Regular' | ||
| ]; | ||
| var isSupportedFont = require('./constants').isSupportedFont; | ||
archmoj marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { | ||
| function coerce(attr, dflt) { | ||
| @@ -104,12 +67,14 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout | ||
| var clusterEnabled = coerce('cluster.enabled', clusterEnabledDflt); | ||
| if(clusterEnabled || subTypes.hasText(traceOut)) { | ||
| var layoutFontFamily = layout.font.family; | ||
| handleTextDefaults(traceIn, traceOut, layout, coerce, | ||
| { | ||
| noSelect: true, | ||
| noFontVariant: true, | ||
| font: { | ||
| family: supportedFonts.indexOf(layout.font.family) !== -1 ? layout.font.family : 'Open Sans Regular', | ||
| family: isSupportedFont(layoutFontFamily) ? layoutFontFamily : 'Open Sans Regular', | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, naive question because I don't quite understand -- if the user passes just ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we have ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I was thinking about that and I'd be happy to work on it in a separate PR. Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, that's fine to do in another PR. Would be nice to have! ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tracked in #6993. | ||
| weight: layout.font.weight, | ||
| style: layout.font.style, | ||
| size: layout.font.size, | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.