fix: map ink transparency to SVG opacity
This commit is contained in:
@@ -82,6 +82,7 @@ const page: OneNotePageDto = {
|
|||||||
],
|
],
|
||||||
width: 2,
|
width: 2,
|
||||||
color: 0xff0000,
|
color: 0xff0000,
|
||||||
|
transparency: 255,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
children: [],
|
children: [],
|
||||||
@@ -127,6 +128,10 @@ describe('PageReader structured content', () => {
|
|||||||
'd',
|
'd',
|
||||||
'M 10 20 L 15 25 30 40'
|
'M 10 20 L 15 25 30 40'
|
||||||
);
|
);
|
||||||
|
expect(document.querySelector('.onenote-ink path')).toHaveAttribute(
|
||||||
|
'stroke-opacity',
|
||||||
|
'0'
|
||||||
|
);
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(
|
expect(
|
||||||
screen.getByRole('img', { name: 'Embedded diagram' })
|
screen.getByRole('img', { name: 'Embedded diagram' })
|
||||||
|
|||||||
@@ -464,7 +464,7 @@ function InkView({ ink }: { ink: OneNoteInkBlock }) {
|
|||||||
strokeOpacity={
|
strokeOpacity={
|
||||||
stroke.transparency === undefined
|
stroke.transparency === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: Math.max(0, Math.min(1, (255 - stroke.transparency) / 256))
|
: Math.max(0, Math.min(1, 1 - stroke.transparency / 255))
|
||||||
}
|
}
|
||||||
strokeLinecap={stroke.penTip === 0 ? 'round' : 'square'}
|
strokeLinecap={stroke.penTip === 0 ? 'round' : 'square'}
|
||||||
strokeLinejoin={stroke.penTip === 0 ? 'round' : 'bevel'}
|
strokeLinejoin={stroke.penTip === 0 ? 'round' : 'bevel'}
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ describe('OneNote export serializers', () => {
|
|||||||
expect(document.querySelectorAll('svg.ink')).toHaveLength(1);
|
expect(document.querySelectorAll('svg.ink')).toHaveLength(1);
|
||||||
expect(
|
expect(
|
||||||
document.querySelector('polyline')?.getAttribute('stroke-opacity')
|
document.querySelector('polyline')?.getAttribute('stroke-opacity')
|
||||||
).toBe('0.496');
|
).toBe('0.498');
|
||||||
expect(
|
expect(
|
||||||
document
|
document
|
||||||
.querySelector('meta[http-equiv="Content-Security-Policy"]')
|
.querySelector('meta[http-equiv="Content-Security-Policy"]')
|
||||||
@@ -111,6 +111,30 @@ describe('OneNote export serializers', () => {
|
|||||||
).toContain("default-src 'none'");
|
).toContain("default-src 'none'");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('maps the full ink transparency byte range to SVG opacity', () => {
|
||||||
|
const snapshot = fixtureSnapshot();
|
||||||
|
const ink = snapshot.sections[0]!.pages[0]!.blocks.find(
|
||||||
|
(block) => block.kind === 'ink'
|
||||||
|
);
|
||||||
|
if (!ink || ink.kind !== 'ink') throw new Error('Ink fixture is missing');
|
||||||
|
ink.strokes[0]!.transparency = 0;
|
||||||
|
ink.strokes.push({
|
||||||
|
...ink.strokes[0]!,
|
||||||
|
points: ink.strokes[0]!.points.map((point) => ({ ...point })),
|
||||||
|
transparency: 255,
|
||||||
|
});
|
||||||
|
|
||||||
|
const document = new DOMParser().parseFromString(
|
||||||
|
serializeOneNoteSemanticHtml(snapshot),
|
||||||
|
'text/html'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
[...document.querySelectorAll('polyline')].map((stroke) =>
|
||||||
|
stroke.getAttribute('stroke-opacity')
|
||||||
|
)
|
||||||
|
).toEqual(['1', '0']);
|
||||||
|
});
|
||||||
|
|
||||||
it('creates a deterministic, path-safe static notebook ZIP', () => {
|
it('creates a deterministic, path-safe static notebook ZIP', () => {
|
||||||
const snapshot = fixtureSnapshot();
|
const snapshot = fixtureSnapshot();
|
||||||
const first = createOneNoteStaticNotebookZip(snapshot);
|
const first = createOneNoteStaticNotebookZip(snapshot);
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ function svgStroke(stroke: OneNoteInkBlock['strokes'][number]): string {
|
|||||||
stroke.transparency !== undefined && Number.isFinite(stroke.transparency)
|
stroke.transparency !== undefined && Number.isFinite(stroke.transparency)
|
||||||
? Math.max(0, Math.min(255, stroke.transparency))
|
? Math.max(0, Math.min(255, stroke.transparency))
|
||||||
: undefined;
|
: undefined;
|
||||||
const opacity = transparency === undefined ? 1 : (255 - transparency) / 256;
|
const opacity = transparency === undefined ? 1 : 1 - transparency / 255;
|
||||||
if (points.length === 1) {
|
if (points.length === 1) {
|
||||||
return `<circle cx="${formatNumber(points[0]!.x)}" cy="${formatNumber(points[0]!.y)}" r="${formatNumber(width / 2)}" fill="${color}" fill-opacity="${formatNumber(opacity)}"/>`;
|
return `<circle cx="${formatNumber(points[0]!.x)}" cy="${formatNumber(points[0]!.y)}" r="${formatNumber(width / 2)}" fill="${color}" fill-opacity="${formatNumber(opacity)}"/>`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user