Add superscript and subscript, and make highlighting stronger [#54]
This commit is contained in:
parent
5deec319df
commit
fc3e11ab5a
|
@ -92,17 +92,17 @@
|
|||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncG').attrs({
|
||||
'intercept': 0.9375,
|
||||
'intercept': 0.875,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncB').attrs({
|
||||
'intercept': 0.09375,
|
||||
'intercept': 0,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncA').attrs({
|
||||
'slope': 0.7,
|
||||
'slope': 0.8,
|
||||
'type': 'linear',
|
||||
})
|
||||
),
|
||||
|
@ -4201,6 +4201,14 @@
|
|||
attrs: {'text-decoration': 'underline'},
|
||||
begin: {matcher: /<u>/g, skip: 0},
|
||||
end: {matcher: /<\/u>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '70%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sup>/g, skip: 0},
|
||||
end: {matcher: /<\/sup>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '-20%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sub>/g, skip: 0},
|
||||
end: {matcher: /<\/sub>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'fill': '#DD0000'},
|
||||
begin: {matcher: /<red>/g, skip: 0},
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -92,17 +92,17 @@
|
|||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncG').attrs({
|
||||
'intercept': 0.9375,
|
||||
'intercept': 0.875,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncB').attrs({
|
||||
'intercept': 0.09375,
|
||||
'intercept': 0,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncA').attrs({
|
||||
'slope': 0.7,
|
||||
'slope': 0.8,
|
||||
'type': 'linear',
|
||||
})
|
||||
),
|
||||
|
@ -4201,6 +4201,14 @@
|
|||
attrs: {'text-decoration': 'underline'},
|
||||
begin: {matcher: /<u>/g, skip: 0},
|
||||
end: {matcher: /<\/u>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '70%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sup>/g, skip: 0},
|
||||
end: {matcher: /<\/sup>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '-20%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sub>/g, skip: 0},
|
||||
end: {matcher: /<\/sub>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'fill': '#DD0000'},
|
||||
begin: {matcher: /<red>/g, skip: 0},
|
||||
|
@ -10630,6 +10638,21 @@
|
|||
return variant.getAdvanceWidth(text, size, OPENTYPE_OPTIONS);
|
||||
}
|
||||
|
||||
function combineAttrs$1(base, next) {
|
||||
if(!next) {
|
||||
return base;
|
||||
}
|
||||
const result = Object.assign({}, base, next);
|
||||
const nextSize = next['font-size'];
|
||||
if(typeof nextSize === 'string' && nextSize.endsWith('em')) {
|
||||
const ratio = Number.parseFloat(
|
||||
nextSize.substr(0, nextSize.length - 2)
|
||||
);
|
||||
result['font-size'] = base['font-size'] * ratio;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class VirtualTextSizer {
|
||||
baseline({attrs}) {
|
||||
return getFontSize(attrs);
|
||||
|
@ -10655,7 +10678,8 @@
|
|||
if(!part.text) {
|
||||
continue;
|
||||
}
|
||||
len += measure(Object.assign({}, attrs, part.attrs), part.text);
|
||||
const combinedAttrs = combineAttrs$1(attrs, part.attrs);
|
||||
len += measure(combinedAttrs, part.text);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,14 @@ const STYLES = [
|
|||
attrs: {'text-decoration': 'underline'},
|
||||
begin: {matcher: /<u>/g, skip: 0},
|
||||
end: {matcher: /<\/u>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '70%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sup>/g, skip: 0},
|
||||
end: {matcher: /<\/sup>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'baseline-shift': '-20%', 'font-size': '0.6em'},
|
||||
begin: {matcher: /<sub>/g, skip: 0},
|
||||
end: {matcher: /<\/sub>/g, skip: 0},
|
||||
}, {
|
||||
attrs: {'fill': '#DD0000'},
|
||||
begin: {matcher: /<red>/g, skip: 0},
|
||||
|
|
|
@ -143,6 +143,32 @@ describe('Markdown Parser', () => {
|
|||
]]);
|
||||
});
|
||||
|
||||
it('recognises superscript styling', () => {
|
||||
const formatted = parser('a <sup>b</sup> c');
|
||||
|
||||
expect(formatted).toEqual([[
|
||||
{attrs: null, text: 'a '},
|
||||
{
|
||||
attrs: {'baseline-shift': '70%', 'font-size': '0.6em'},
|
||||
text: 'b',
|
||||
},
|
||||
{attrs: null, text: ' c'},
|
||||
]]);
|
||||
});
|
||||
|
||||
it('recognises subscript styling', () => {
|
||||
const formatted = parser('a <sub>b</sub> c');
|
||||
|
||||
expect(formatted).toEqual([[
|
||||
{attrs: null, text: 'a '},
|
||||
{
|
||||
attrs: {'baseline-shift': '-20%', 'font-size': '0.6em'},
|
||||
text: 'b',
|
||||
},
|
||||
{attrs: null, text: ' c'},
|
||||
]]);
|
||||
});
|
||||
|
||||
it('recognises red styling', () => {
|
||||
const formatted = parser('a <red>b</red> c');
|
||||
|
||||
|
|
|
@ -89,17 +89,17 @@ export default class BaseTheme {
|
|||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncG').attrs({
|
||||
'intercept': 0.9375,
|
||||
'intercept': 0.875,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncB').attrs({
|
||||
'intercept': 0.09375,
|
||||
'intercept': 0,
|
||||
'slope': 0,
|
||||
'type': 'linear',
|
||||
}),
|
||||
this.svg.el('feFuncA').attrs({
|
||||
'slope': 0.7,
|
||||
'slope': 0.8,
|
||||
'type': 'linear',
|
||||
})
|
||||
),
|
||||
|
|
|
@ -93,6 +93,21 @@ function measure(attrs, text) {
|
|||
return variant.getAdvanceWidth(text, size, OPENTYPE_OPTIONS);
|
||||
}
|
||||
|
||||
function combineAttrs(base, next) {
|
||||
if(!next) {
|
||||
return base;
|
||||
}
|
||||
const result = Object.assign({}, base, next);
|
||||
const nextSize = next['font-size'];
|
||||
if(typeof nextSize === 'string' && nextSize.endsWith('em')) {
|
||||
const ratio = Number.parseFloat(
|
||||
nextSize.substr(0, nextSize.length - 2)
|
||||
);
|
||||
result['font-size'] = base['font-size'] * ratio;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export default class VirtualTextSizer {
|
||||
baseline({attrs}) {
|
||||
return getFontSize(attrs);
|
||||
|
@ -118,7 +133,8 @@ export default class VirtualTextSizer {
|
|||
if(!part.text) {
|
||||
continue;
|
||||
}
|
||||
len += measure(Object.assign({}, attrs, part.attrs), part.text);
|
||||
const combinedAttrs = combineAttrs(attrs, part.attrs);
|
||||
len += measure(combinedAttrs, part.text);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,18 @@ describe('VirtualTextSizer', () => {
|
|||
expect(sizeMonoBold.width).toBeNear(sizeMono.width, 1e-1);
|
||||
});
|
||||
|
||||
it('uses relative font sizes', () => {
|
||||
const size = safeMeasure(attrs, [[
|
||||
{text: 'bar'},
|
||||
]]);
|
||||
|
||||
const sizeSmall = safeMeasure(attrs, [[
|
||||
{attrs: {'font-size': '0.5em'}, text: 'bar'},
|
||||
]]);
|
||||
|
||||
expect(sizeSmall.width).toBeNear(size.width / 2, 1e-1);
|
||||
});
|
||||
|
||||
it('returns 0, 0 for empty content', () => {
|
||||
const size = safeMeasure(attrs, []);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<svg width="96.6966781616211" height="124" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-48.34833908081055 -119 96.6966781616211 124"><metadata>title "Foo **Bar**
|
||||
_Baz_ `Zig`
|
||||
<svg width="103.81134033203125" height="124" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-51.905670166015625 -119 103.81134033203125 124"><metadata>title "Foo **Bar** I<sup>2</sup>
|
||||
_Baz_ `Zig` I<sub>2</sub>
|
||||
**_`Zag`_** <u><o>~Abc~</o></u>
|
||||
<highlight>Back</highlight> <red>Text</red>"
|
||||
</metadata><defs><filter id="R0highlight"><feMorphology in="SourceAlpha" operator="dilate" radius="4"></feMorphology><feGaussianBlur edgeMode="none" stdDeviation="3, 1.5"></feGaussianBlur><feComponentTransfer><feFuncA intercept="-70" slope="100" type="linear"></feFuncA></feComponentTransfer><feComponentTransfer><feFuncR intercept="1" slope="0" type="linear"></feFuncR><feFuncG intercept="0.9375" slope="0" type="linear"></feFuncG><feFuncB intercept="0.09375" slope="0" type="linear"></feFuncB><feFuncA slope="0.7" type="linear"></feFuncA></feComponentTransfer><feMerge><feMergeNode></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></defs><defs><mask id="R0FullMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.6966781616211" x="-48.34833908081055" y="-119"></rect></mask><mask id="R0LineMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="96.6966781616211" x="-48.34833908081055" y="-119"></rect></mask></defs><g></g><g><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-94">Foo <tspan font-weight="bolder">Bar</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-68"><tspan font-style="italic">Baz</tspan> <tspan font-family="Courier New,Liberation Mono,monospace">Zig</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-42"><tspan font-style="italic" font-weight="bolder" font-family="Courier New,Liberation Mono,monospace">Zag</tspan> <tspan text-decoration="line-through overline underline">Abc</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-16"><tspan filter="url(#R0highlight)">Back</tspan> <tspan fill="#DD0000">Text</tspan></text></g><g></g><g mask="url(#R0FullMask)"><g mask="url(#R0LineMask)"></g><g></g><g></g></g></svg>
|
||||
</metadata><defs><filter id="R0highlight"><feMorphology in="SourceAlpha" operator="dilate" radius="4"></feMorphology><feGaussianBlur edgeMode="none" stdDeviation="3, 1.5"></feGaussianBlur><feComponentTransfer><feFuncA intercept="-70" slope="100" type="linear"></feFuncA></feComponentTransfer><feComponentTransfer><feFuncR intercept="1" slope="0" type="linear"></feFuncR><feFuncG intercept="0.875" slope="0" type="linear"></feFuncG><feFuncB intercept="0" slope="0" type="linear"></feFuncB><feFuncA slope="0.8" type="linear"></feFuncA></feComponentTransfer><feMerge><feMergeNode></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode></feMerge></filter></defs><defs><mask id="R0FullMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="103.81134033203125" x="-51.905670166015625" y="-119"></rect></mask><mask id="R0LineMask" maskUnits="userSpaceOnUse"><rect fill="#FFFFFF" height="124" width="103.81134033203125" x="-51.905670166015625" y="-119"></rect></mask></defs><g></g><g><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-94">Foo <tspan font-weight="bolder">Bar</tspan> I<tspan baseline-shift="70%" font-size="0.6em">2</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-68"><tspan font-style="italic">Baz</tspan> <tspan font-family="Courier New,Liberation Mono,monospace">Zig</tspan> I<tspan baseline-shift="-20%" font-size="0.6em">2</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-42"><tspan font-style="italic" font-weight="bolder" font-family="Courier New,Liberation Mono,monospace">Zag</tspan> <tspan text-decoration="line-through overline underline">Abc</tspan></text><text x="0" class="title" font-family="Helvetica,Arial,Liberation Sans,sans-serif" font-size="20" line-height="1.3" text-anchor="middle" y="-16"><tspan filter="url(#R0highlight)">Back</tspan> <tspan fill="#DD0000">Text</tspan></text></g><g></g><g mask="url(#R0FullMask)"><g mask="url(#R0LineMask)"></g><g></g><g></g></g></svg>
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.5 KiB |
Loading…
Reference in New Issue