Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c7b1003

Browse filesBrowse files
authored
Merge pull request #6983 from plotly/font-shadow-striding-capitalize
Add `shadow`, `lineposition` and `textcase` options to SVG fonts
2 parents cfccbcc + e60123f commit c7b1003
Copy full SHA for c7b1003

File tree

130 files changed

+12464
-174
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner

130 files changed

+12464
-174
lines changed

‎src/components/annotations/draw.js

Copy file name to clipboardExpand all lines: src/components/annotations/draw.js
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ function drawRaw(gd, options, index, subplotId, xa, ya) {
198198
fontColor: hoverFont.color,
199199
fontWeight: hoverFont.weight,
200200
fontStyle: hoverFont.style,
201-
fontVariant: hoverFont.variant
201+
fontVariant: hoverFont.variant,
202+
fontShadow: hoverFont.fontShadow,
203+
fontLineposition: hoverFont.fontLineposition,
204+
fontTextcase: hoverFont.fontTextcase,
202205
}, {
203206
container: fullLayout._hoverlayer.node(),
204207
outerContainer: fullLayout._paper.node(),

‎src/components/colorbar/defaults.js

Copy file name to clipboardExpand all lines: src/components/colorbar/defaults.js
+3-5Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,9 @@ module.exports = function colorbarDefaults(containerIn, containerOut, layout) {
124124
coerce('title.text', layout._dfltTitle.colorbar);
125125

126126
var tickFont = colorbarOut.showticklabels ? colorbarOut.tickfont : font;
127-
var dfltTitleFont = Lib.extendFlat({}, tickFont, {
128-
weight: font.weight,
129-
style: font.style,
130-
variant: font.variant,
131-
color: font.color,
127+
128+
var dfltTitleFont = Lib.extendFlat({}, font, {
129+
family: tickFont.family,
132130
size: Lib.bigFont(tickFont.size)
133131
});
134132
Lib.coerceFont(coerce, 'title.font', dfltTitleFont);

‎src/components/drawing/index.js

Copy file name to clipboardExpand all lines: src/components/drawing/index.js
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ drawing.font = function(s, font) {
3434
var color = font.color;
3535
var size = font.size;
3636
var family = font.family;
37+
var shadow = font.shadow;
38+
var lineposition = font.lineposition;
39+
var textcase = font.textcase;
3740

3841
if(family) s.style('font-family', family);
3942
if(size + 1) s.style('font-size', size + 'px');
@@ -42,8 +45,38 @@ drawing.font = function(s, font) {
4245
if(weight) s.style('font-weight', weight);
4346
if(style) s.style('font-style', style);
4447
if(variant) s.style('font-variant', variant);
48+
49+
if(textcase) s.style('text-transform', dropNone(textcase2transform(textcase)));
50+
if(shadow) s.style('text-shadow', shadow === 'auto' ? svgTextUtils.makeTextShadow(Color.contrast(color)) : dropNone(shadow));
51+
if(lineposition) s.style('text-decoration-line', dropNone(lineposition2decorationLine(lineposition)));
52+
};
53+
54+
function dropNone(a) {
55+
return a === 'none' ? undefined : a;
56+
}
57+
58+
var textcase2transformOptions = {
59+
normal: 'none',
60+
lower: 'lowercase',
61+
upper: 'uppercase',
62+
'word caps': 'capitalize'
4563
};
4664

65+
function textcase2transform(textcase) {
66+
return textcase2transformOptions[textcase];
67+
}
68+
69+
function lineposition2decorationLine(lineposition) {
70+
return (
71+
lineposition
72+
.replace('under', 'underline')
73+
.replace('over', 'overline')
74+
.replace('through', 'line-through')
75+
.split('+')
76+
.join(' ')
77+
);
78+
}
79+
4780
/*
4881
* Positioning helpers
4982
* Note: do not use `setPosition` with <text> nodes modified by
@@ -1136,6 +1169,9 @@ drawing.textPointStyle = function(s, trace, gd) {
11361169
weight: d.tw || trace.textfont.weight,
11371170
style: d.ty || trace.textfont.style,
11381171
variant: d.tv || trace.textfont.variant,
1172+
textcase: d.tC || trace.textfont.textcase,
1173+
lineposition: d.tE || trace.textfont.lineposition,
1174+
shadow: d.tS || trace.textfont.shadow,
11391175
size: fontSize,
11401176
color: fontColor
11411177
})

‎src/components/fx/hover.js

Copy file name to clipboardExpand all lines: src/components/fx/hover.js
+24-8Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,9 @@ function createHoverText(hoverData, opts) {
961961
var fontWeight = opts.fontWeight || fullLayout.font.weight;
962962
var fontStyle = opts.fontStyle || fullLayout.font.style;
963963
var fontVariant = opts.fontVariant || fullLayout.font.variant;
964+
var fontTextcase = opts.fontTextcase || fullLayout.font.textcase;
965+
var fontLineposition = opts.fontLineposition || fullLayout.font.lineposition;
966+
var fontShadow = opts.fontShadow || fullLayout.font.shadow;
964967

965968
var c0 = hoverData[0];
966969
var xa = c0.xa;
@@ -1041,13 +1044,17 @@ function createHoverText(hoverData, opts) {
10411044
var commonBgColor = commonLabelOpts.bgcolor || Color.defaultLine;
10421045
var commonStroke = commonLabelOpts.bordercolor || Color.contrast(commonBgColor);
10431046
var contrastColor = Color.contrast(commonBgColor);
1047+
var commonLabelOptsFont = commonLabelOpts.font;
10441048
var commonLabelFont = {
1045-
weight: commonLabelOpts.font.weight || fontWeight,
1046-
style: commonLabelOpts.font.style || fontStyle,
1047-
variant: commonLabelOpts.font.variant || fontVariant,
1048-
family: commonLabelOpts.font.family || fontFamily,
1049-
size: commonLabelOpts.font.size || fontSize,
1050-
color: commonLabelOpts.font.color || contrastColor
1049+
weight: commonLabelOptsFont.weight || fontWeight,
1050+
style: commonLabelOptsFont.style || fontStyle,
1051+
variant: commonLabelOptsFont.variant || fontVariant,
1052+
textcase: commonLabelOptsFont.textcase || fontTextcase,
1053+
lineposition: commonLabelOptsFont.lineposition || fontLineposition,
1054+
shadow: commonLabelOptsFont.shadow || fontShadow,
1055+
family: commonLabelOptsFont.family || fontFamily,
1056+
size: commonLabelOptsFont.size || fontSize,
1057+
color: commonLabelOptsFont.color || contrastColor
10511058
};
10521059

10531060
lpath.style({
@@ -1370,6 +1377,9 @@ function createHoverText(hoverData, opts) {
13701377
weight: fontWeight,
13711378
style: fontStyle,
13721379
variant: fontVariant,
1380+
textcase: fontTextcase,
1381+
lineposition: fontLineposition,
1382+
shadow: fontShadow,
13731383
family: fontFamily,
13741384
size: fontSize
13751385
});
@@ -1413,7 +1423,10 @@ function createHoverText(hoverData, opts) {
14131423
color: d.fontColor || contrastColor,
14141424
weight: d.fontWeight || fontWeight,
14151425
style: d.fontStyle || fontStyle,
1416-
variant: d.fontVariant || fontVariant
1426+
variant: d.fontVariant || fontVariant,
1427+
textcase: d.fontTextcase || fontTextcase,
1428+
lineposition: d.fontLineposition || fontLineposition,
1429+
shadow: d.fontShadow || fontShadow,
14171430
})
14181431
.text(text)
14191432
.attr('data-notex', 1)
@@ -1432,7 +1445,10 @@ function createHoverText(hoverData, opts) {
14321445
color: nameColor,
14331446
weight: d.fontWeight || fontWeight,
14341447
style: d.fontStyle || fontStyle,
1435-
variant: d.fontVariant || fontVariant
1448+
variant: d.fontVariant || fontVariant,
1449+
textcase: d.fontTextcase || fontTextcase,
1450+
lineposition: d.fontLineposition || fontLineposition,
1451+
shadow: d.fontShadow || fontShadow,
14361452
}).text(name)
14371453
.attr('data-notex', 1)
14381454
.call(svgTextUtils.positionText, 0, 0)

‎src/components/legend/defaults.js

Copy file name to clipboardExpand all lines: src/components/legend/defaults.js
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ function groupDefaults(legendId, layoutIn, layoutOut, fullData) {
3333
};
3434

3535
var globalFont = layoutOut.font || {};
36-
var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', Lib.extendFlat({}, globalFont, {
36+
var grouptitlefont = Lib.coerceFont(coerce, 'grouptitlefont', globalFont, { overrideDflt: {
3737
size: Math.round(globalFont.size * 1.1)
38-
}));
38+
}});
3939

4040
var legendTraceCount = 0;
4141
var legendReallyHasATrace = false;

‎src/components/legend/style.js

Copy file name to clipboardExpand all lines: src/components/legend/style.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ module.exports = function style(s, gd, legend) {
247247
dEdit.tw = boundVal('textfont.weight', pickFirst);
248248
dEdit.ty = boundVal('textfont.style', pickFirst);
249249
dEdit.tv = boundVal('textfont.variant', pickFirst);
250+
dEdit.tC = boundVal('textfont.textcase', pickFirst);
251+
dEdit.tE = boundVal('textfont.lineposition', pickFirst);
252+
dEdit.tS = boundVal('textfont.shadow', pickFirst);
250253
}
251254

252255
dMod = [Lib.minExtend(d0, dEdit)];

‎src/components/titles/index.js

Copy file name to clipboardExpand all lines: src/components/titles/index.js
+14-8Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ function draw(gd, titleClass, options) {
7171
var fontWeight = font.weight;
7272
var fontStyle = font.style;
7373
var fontVariant = font.variant;
74+
var fontTextcase = font.textcase;
75+
var fontLineposition = font.lineposition;
76+
var fontShadow = font.shadow;
7477

7578
// only make this title editable if we positively identify its property
7679
// as one that has editing enabled.
@@ -144,14 +147,17 @@ function draw(gd, titleClass, options) {
144147

145148
titleEl.attr('transform', transformVal);
146149

147-
titleEl.style({
148-
'font-family': fontFamily,
149-
'font-size': d3.round(fontSize, 2) + 'px',
150-
fill: Color.rgb(fontColor),
151-
opacity: opacity * Color.opacity(fontColor),
152-
'font-weight': fontWeight,
153-
'font-style': fontStyle,
154-
'font-variant': fontVariant
150+
titleEl.style('opacity', opacity * Color.opacity(fontColor))
151+
.call(Drawing.font, {
152+
color: Color.rgb(fontColor),
153+
size: d3.round(fontSize, 2),
154+
family: fontFamily,
155+
weight: fontWeight,
156+
style: fontStyle,
157+
variant: fontVariant,
158+
textcase: fontTextcase,
159+
shadow: fontShadow,
160+
lineposition: fontLineposition,
155161
})
156162
.attr(attributes)
157163
.call(svgTextUtils.convertToTspans, gd);

‎src/lib/coerce.js

Copy file name to clipboardExpand all lines: src/lib/coerce.js
+20-9Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
var isNumeric = require('fast-isnumeric');
44
var tinycolor = require('tinycolor2');
55

6+
var extendFlat = require('./extend').extendFlat;
7+
68
var baseTraceAttrs = require('../plots/attributes');
79
var colorscales = require('../components/colorscale/scales');
810
var Color = require('../components/color');
@@ -470,18 +472,27 @@ exports.coerce2 = function(containerIn, containerOut, attributes, attribute, dfl
470472
*/
471473
exports.coerceFont = function(coerce, attr, dfltObj, opts) {
472474
if(!opts) opts = {};
475+
dfltObj = extendFlat({}, dfltObj);
476+
dfltObj = extendFlat(dfltObj, opts.overrideDflt || {});
473477

474-
var out = {};
475-
476-
dfltObj = dfltObj || {};
477-
478-
out.family = coerce(attr + '.family', dfltObj.family);
479-
out.size = coerce(attr + '.size', dfltObj.size);
480-
out.color = coerce(attr + '.color', dfltObj.color);
478+
var out = {
479+
family: coerce(attr + '.family', dfltObj.family),
480+
size: coerce(attr + '.size', dfltObj.size),
481+
color: coerce(attr + '.color', dfltObj.color),
482+
weight: coerce(attr + '.weight', dfltObj.weight),
483+
style: coerce(attr + '.style', dfltObj.style),
484+
};
481485

482-
out.weight = coerce(attr + '.weight', dfltObj.weight);
483-
out.style = coerce(attr + '.style', dfltObj.style);
484486
if(!opts.noFontVariant) out.variant = coerce(attr + '.variant', dfltObj.variant);
487+
if(!opts.noFontLineposition) out.lineposition = coerce(attr + '.lineposition', dfltObj.lineposition);
488+
if(!opts.noFontTextcase) out.textcase = coerce(attr + '.textcase', dfltObj.textcase);
489+
if(!opts.noFontShadow) {
490+
var dfltShadow = dfltObj.shadow;
491+
if(dfltShadow === 'none' && opts.autoShadowDflt) {
492+
dfltShadow = 'auto';
493+
}
494+
out.shadow = coerce(attr + '.shadow', dfltShadow);
495+
}
485496

486497
return out;
487498
};

‎src/plots/cartesian/axes.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/axes.js
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,9 @@ function tickTextObj(ax, x, text) {
17401740
fontWeight: tf.weight,
17411741
fontStyle: tf.style,
17421742
fontVariant: tf.variant,
1743+
fontTextcase: tf.textcase,
1744+
fontLineposition: tf.lineposition,
1745+
fontShadow: tf.shadow,
17431746
fontColor: tf.color
17441747
};
17451748
}
@@ -3507,7 +3510,10 @@ axes.drawLabels = function(gd, ax, opts) {
35073510
color: d.fontColor,
35083511
weight: d.fontWeight,
35093512
style: d.fontStyle,
3510-
variant: d.fontVariant
3513+
variant: d.fontVariant,
3514+
textcase: d.fontTextcase,
3515+
lineposition: d.fontLineposition,
3516+
shadow: d.fontShadow,
35113517
})
35123518
.text(d.text)
35133519
.call(svgTextUtils.convertToTspans, gd);

‎src/plots/cartesian/axis_defaults.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/axis_defaults.js
+2-6Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,10 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
111111
if(!visible) return containerOut;
112112

113113
coerce('title.text', dfltTitle);
114-
Lib.coerceFont(coerce, 'title.font', {
115-
family: font.family,
116-
weight: font.weight,
117-
style: font.style,
118-
variant: font.variant,
114+
Lib.coerceFont(coerce, 'title.font', font, { overrideDflt: {
119115
size: Lib.bigFont(font.size),
120116
color: dfltFontColor
121-
});
117+
}});
122118

123119
// major ticks
124120
handleTickValueDefaults(containerIn, containerOut, coerce, axType);

‎src/plots/cartesian/tick_label_defaults.js

Copy file name to clipboardExpand all lines: src/plots/cartesian/tick_label_defaults.js
+2-7Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,9 @@ module.exports = function handleTickLabelDefaults(containerIn, containerOut, coe
2626
(contColor && contColor !== layoutAttributes.color.dflt) ?
2727
contColor : font.color;
2828

29-
Lib.coerceFont(coerce, 'tickfont', {
30-
family: font.family,
31-
weight: font.weight,
32-
style: font.style,
33-
variant: font.variant,
34-
size: font.size,
29+
Lib.coerceFont(coerce, 'tickfont', font, { overrideDflt: {
3530
color: dfltFontColor
36-
});
31+
}});
3732

3833
if(
3934
!options.noTicklabelstep &&

‎src/plots/font_attributes.js

Copy file name to clipboardExpand all lines: src/plots/font_attributes.js
+48-1Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,42 @@ module.exports = function(opts) {
9999
].join(' ')
100100
},
101101

102+
textcase: opts.noFontTextcase ? undefined : {
103+
editType: editType,
104+
valType: 'enumerated',
105+
values: ['normal', 'word caps', 'upper', 'lower'],
106+
dflt: 'normal',
107+
description: [
108+
'Sets capitalization of text.',
109+
'It can be used to make text appear in all-uppercase or all-lowercase,',
110+
'or with each word capitalized.'
111+
].join(' ')
112+
},
113+
114+
lineposition: opts.noFontLineposition ? undefined : {
115+
editType: editType,
116+
valType: 'flaglist',
117+
flags: ['under', 'over', 'through'],
118+
extras: ['none'],
119+
dflt: 'none',
120+
description: [
121+
'Sets the kind of decoration line(s) with text,',
122+
'such as an *under*, *over* or *through*',
123+
'as well as combinations e.g. *under+over*, etc.'
124+
].join(' ')
125+
},
126+
127+
shadow: opts.noFontShadow ? undefined : {
128+
editType: editType,
129+
valType: 'string',
130+
dflt: opts.autoShadowDflt ? 'auto' : 'none',
131+
description: [
132+
'Sets the shape and color of the shadow behind text.',
133+
'*auto* places minimal shadow and applies contrast text font color.',
134+
'See https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow for additional options.'
135+
].join(' ')
136+
},
137+
102138
editType: editType,
103139
// blank strings so compress_attributes can remove
104140
// TODO - that's uber hacky... better solution?
@@ -112,7 +148,18 @@ module.exports = function(opts) {
112148
attrs.family.arrayOk = true;
113149
attrs.weight.arrayOk = true;
114150
attrs.style.arrayOk = true;
115-
attrs.variant.arrayOk = true;
151+
if(!opts.noFontVariant) {
152+
attrs.variant.arrayOk = true;
153+
}
154+
if(!opts.noFontTextcase) {
155+
attrs.textcase.arrayOk = true;
156+
}
157+
if(!opts.noFontLineposition) {
158+
attrs.lineposition.arrayOk = true;
159+
}
160+
if(!opts.noFontShadow) {
161+
attrs.shadow.arrayOk = true;
162+
}
116163
attrs.size.arrayOk = true;
117164
attrs.color.arrayOk = true;
118165
}

‎src/plots/mapbox/layout_attributes.js

Copy file name to clipboardExpand all lines: src/plots/mapbox/layout_attributes.js
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ var constants = require('./constants');
1212

1313
var fontAttr = fontAttrs({
1414
noFontVariant: true,
15+
noFontShadow: true,
16+
noFontLineposition: true,
17+
noFontTextcase: true,
1518
description: [
1619
'Sets the icon text font (color=mapbox.layer.paint.text-color, size=mapbox.layer.layout.text-size).',
1720
'Has an effect only when `type` is set to *symbol*.'

‎src/plots/mapbox/layout_defaults.js

Copy file name to clipboardExpand all lines: src/plots/mapbox/layout_defaults.js
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ function handleLayerDefaults(layerIn, layerOut) {
104104

105105
coerce('symbol.text');
106106
Lib.coerceFont(coerce, 'symbol.textfont', undefined, {
107-
noFontVariant: true
107+
noFontVariant: true,
108+
noFontShadow: true,
109+
noFontLineposition: true,
110+
noFontTextcase: true,
108111
});
109112
coerce('symbol.textposition');
110113
coerce('symbol.placement');

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.