-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Changes from all commits
37dee48
3212866
448eb80
3a3f458
15b25a5
be24a14
d8424a3
353efc4
abb3fc8
8266a6d
46e6b27
3e4942a
72044b5
4d52885
b92ef23
b125396
54005b9
09f4dd3
f67b40c
99162e5
990fa8d
f3c0356
a5cc7f8
63824c1
190aef1
091e7d3
82de3ff
59779f3
f6fcbd7
10f477f
82863fd
bff00ac
48d057f
File filter
Filter by extension
Conversations
Jump to
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'], | ||
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? 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. 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 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 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.
Show resolved
Hide resolved
|
||
|
||
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.
Show resolved
Hide resolved
|
||
|
||
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.
Show resolved
Hide resolved
|
||
|
||
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), | ||
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. Why is this needed if we are already disallowing numeric weight values at the schema level? 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. 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. gotcha, thank you. Could you perhaps add that as a comment above the function definition? 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 48d057f. |
||
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'; | ||
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? 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 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 = [ | ||
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. 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 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 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. 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') { | ||
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 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'; | ||
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 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 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. 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.
Show resolved
Hide resolved
|
||
|
||
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', | ||
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 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. 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 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. 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! 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.