reamkit 1.22.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/core/bmp.d.ts +33 -0
- package/dist/esm/core/bmp.js +276 -0
- package/dist/esm/core/converter/ream.d.ts +16 -0
- package/dist/esm/core/converter/ream.js +59 -9
- package/dist/esm/core/document-model/types.d.ts +55 -0
- package/dist/esm/core/drawingml/chart-geometry.js +14 -7
- package/dist/esm/core/drawingml/colors.d.ts +4 -2
- package/dist/esm/core/drawingml/colors.js +15 -0
- package/dist/esm/core/drawingml/diagram/colors.d.ts +52 -0
- package/dist/esm/core/drawingml/diagram/colors.js +125 -0
- package/dist/esm/core/drawingml/diagram/data-model.d.ts +47 -0
- package/dist/esm/core/drawingml/diagram/data-model.js +119 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.d.ts +46 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.js +948 -0
- package/dist/esm/core/drawingml/diagram/run.d.ts +37 -0
- package/dist/esm/core/drawingml/diagram/run.js +50 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.d.ts +16 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.js +86 -0
- package/dist/esm/core/drawingml/preset-geometry.js +116 -6
- package/dist/esm/core/drawingml/text-warp.d.ts +58 -0
- package/dist/esm/core/drawingml/text-warp.js +355 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
- package/dist/esm/core/drawingml/theme-parser.js +73 -4
- package/dist/esm/core/font/measure.d.ts +12 -0
- package/dist/esm/core/font/measure.js +36 -0
- package/dist/esm/core/fonts/families.d.ts +10 -0
- package/dist/esm/core/fonts/families.js +44 -0
- package/dist/esm/core/fonts/index.d.ts +3 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
- package/dist/esm/core/fonts/remote-fonts.js +114 -8
- package/dist/esm/core/fonts/scripts.d.ts +26 -0
- package/dist/esm/core/fonts/scripts.js +177 -0
- package/dist/esm/core/images.d.ts +30 -2
- package/dist/esm/core/images.js +121 -5
- package/dist/esm/core/metafile/blit.d.ts +33 -0
- package/dist/esm/core/metafile/blit.js +67 -0
- package/dist/esm/core/metafile/dib.d.ts +61 -0
- package/dist/esm/core/metafile/dib.js +205 -0
- package/dist/esm/core/metafile/emf.js +280 -38
- package/dist/esm/core/metafile/picture.d.ts +61 -1
- package/dist/esm/core/metafile/picture.js +70 -1
- package/dist/esm/core/metafile/wmf.js +202 -13
- package/dist/esm/core/ole/escher-blip.d.ts +12 -0
- package/dist/esm/core/ole/escher-blip.js +98 -0
- package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
- package/dist/esm/excel/print-model.js +5 -3
- package/dist/esm/excel/sheet-drawing.js +1 -1
- package/dist/esm/excel/sheet-to-flow.js +16 -2
- package/dist/esm/excel/styles-parser.js +1 -1
- package/dist/esm/excel/xls/biff-reader.js +53 -18
- package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
- package/dist/esm/excel/xls/biff-styles.js +9 -7
- package/dist/esm/excel/xls/escher.js +90 -24
- package/dist/esm/html/html-writer.js +2 -1
- package/dist/esm/layout/page-doc.d.ts +74 -0
- package/dist/esm/layout/page-doc.js +14 -1
- package/dist/esm/layout/styled-layout.d.ts +2 -2
- package/dist/esm/layout/styled-layout.js +475 -48
- package/dist/esm/pdf/shading.js +8 -6
- package/dist/esm/pdf/styled-page-emitter.js +77 -5
- package/dist/esm/pdf/vector-graphics.js +1 -1
- package/dist/esm/pdf-reader/image-decode.js +1 -1
- package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
- package/dist/esm/pptx/embedded-fonts.js +104 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +73 -6
- package/dist/esm/pptx/placeholder-cascade.js +114 -18
- package/dist/esm/pptx/ppt/ppt-reader.js +191 -13
- package/dist/esm/pptx/ppt/ppt-text.d.ts +107 -1
- package/dist/esm/pptx/ppt/ppt-text.js +873 -144
- package/dist/esm/pptx/pptx-reader.d.ts +8 -0
- package/dist/esm/pptx/pptx-reader.js +117 -15
- package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
- package/dist/esm/pptx/preset-table-styles.js +27 -0
- package/dist/esm/pptx/slide-parser.d.ts +11 -2
- package/dist/esm/pptx/slide-parser.js +203 -44
- package/dist/esm/pptx/sp-helpers.d.ts +9 -4
- package/dist/esm/pptx/sp-helpers.js +48 -9
- package/dist/esm/pptx/table-style.d.ts +16 -1
- package/dist/esm/pptx/table-style.js +104 -10
- package/dist/esm/svg/svg-writer.js +1 -0
- package/dist/esm/word/document-parser.d.ts +11 -2
- package/dist/esm/word/document-parser.js +10 -7
- package/dist/esm/word/docx-reader.js +32 -16
- package/dist/esm/word/docx-to-pdf.d.ts +8 -7
- package/dist/esm/word/docx-to-pdf.js +25 -7
- package/dist/esm/word/docx-writer.js +4 -0
- package/dist/esm/word/drawing-parser.d.ts +20 -0
- package/dist/esm/word/drawing-parser.js +67 -22
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +6 -6
- package/dist/esm/word/paragraph-properties.d.ts +2 -1
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.d.ts +5 -2
- package/dist/esm/word/run-properties.js +13 -8
- package/dist/esm/word/styles-parser.d.ts +2 -1
- package/dist/esm/word/styles-parser.js +12 -12
- package/dist/esm/word/table-parser.js +6 -3
- package/dist/esm/word/theme-fonts.d.ts +10 -0
- package/dist/esm/word/theme-fonts.js +28 -0
- package/package.json +1 -1
- /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { PoNode } from '../../po-helpers.js';
|
|
2
|
+
/** The parts a diagram is run from, as the reader resolved them. */
|
|
3
|
+
export interface DiagramParts {
|
|
4
|
+
readonly data: Uint8Array;
|
|
5
|
+
readonly layout?: Uint8Array | undefined;
|
|
6
|
+
readonly colors?: Uint8Array | undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The picture a drawing part caches, when it caches one at all.
|
|
10
|
+
*
|
|
11
|
+
* A generator may write the drawing part and put nothing in it — the group
|
|
12
|
+
* properties and no `dsp:sp` at all. That is a placeholder the generator never
|
|
13
|
+
* got round to filling, not a diagram drawn as empty, and taking it at its word
|
|
14
|
+
* paints a blank frame over a diagram whose data, layout and colours are all
|
|
15
|
+
* present. So an empty tree reads as no tree, and the caller runs the layout
|
|
16
|
+
* exactly as it does for a file that ships no drawing part in the first place.
|
|
17
|
+
*
|
|
18
|
+
* @param drawing The drawing part's bytes.
|
|
19
|
+
* @param parse The reader's XML parser.
|
|
20
|
+
* @returns The cached `dsp:spTree`, or undefined when there is none to use.
|
|
21
|
+
*/
|
|
22
|
+
export declare function cachedDiagramTree(drawing: Uint8Array, parse: (bytes: Uint8Array) => Array<PoNode>): PoNode | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The `dsp:spTree` a diagram's own parts describe, for a file that ships no
|
|
25
|
+
* cached drawing.
|
|
26
|
+
*
|
|
27
|
+
* @param parts The diagram's data, layout and colours parts.
|
|
28
|
+
* @param frame The extent the drawing gives the diagram, in EMU.
|
|
29
|
+
* @param parse The reader's XML parser (the same tree shape either way).
|
|
30
|
+
* @returns The shape tree, or undefined when there is no layout part or the
|
|
31
|
+
* layout uses an algorithm this engine does not run — the caller then
|
|
32
|
+
* reports the diagram as a loss exactly as before.
|
|
33
|
+
*/
|
|
34
|
+
export declare function laidOutDiagramTree(parts: DiagramParts, frame: {
|
|
35
|
+
readonly cx: number;
|
|
36
|
+
readonly cy: number;
|
|
37
|
+
}, parse: (bytes: Uint8Array) => Array<PoNode>): PoNode | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { poChildren, poFindDescendant, poIs } from "../../po-helpers.js";
|
|
2
|
+
import { DiagramColors } from "./colors.js";
|
|
3
|
+
import { DiagramData } from "./data-model.js";
|
|
4
|
+
import { layoutDiagram } from "./layout-engine.js";
|
|
5
|
+
import { diagramDrawingXml } from "./to-drawing.js";
|
|
6
|
+
//#region src/core/drawingml/diagram/run.ts
|
|
7
|
+
/**
|
|
8
|
+
* The picture a drawing part caches, when it caches one at all.
|
|
9
|
+
*
|
|
10
|
+
* A generator may write the drawing part and put nothing in it — the group
|
|
11
|
+
* properties and no `dsp:sp` at all. That is a placeholder the generator never
|
|
12
|
+
* got round to filling, not a diagram drawn as empty, and taking it at its word
|
|
13
|
+
* paints a blank frame over a diagram whose data, layout and colours are all
|
|
14
|
+
* present. So an empty tree reads as no tree, and the caller runs the layout
|
|
15
|
+
* exactly as it does for a file that ships no drawing part in the first place.
|
|
16
|
+
*
|
|
17
|
+
* @param drawing The drawing part's bytes.
|
|
18
|
+
* @param parse The reader's XML parser.
|
|
19
|
+
* @returns The cached `dsp:spTree`, or undefined when there is none to use.
|
|
20
|
+
*/
|
|
21
|
+
function cachedDiagramTree(drawing, parse) {
|
|
22
|
+
for (const root of parse(drawing)) {
|
|
23
|
+
const found = poFindDescendant(root, "dsp:spTree");
|
|
24
|
+
if (found && poChildren(found).some((c) => poIs(c, "dsp:sp"))) return found;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `dsp:spTree` a diagram's own parts describe, for a file that ships no
|
|
29
|
+
* cached drawing.
|
|
30
|
+
*
|
|
31
|
+
* @param parts The diagram's data, layout and colours parts.
|
|
32
|
+
* @param frame The extent the drawing gives the diagram, in EMU.
|
|
33
|
+
* @param parse The reader's XML parser (the same tree shape either way).
|
|
34
|
+
* @returns The shape tree, or undefined when there is no layout part or the
|
|
35
|
+
* layout uses an algorithm this engine does not run — the caller then
|
|
36
|
+
* reports the diagram as a loss exactly as before.
|
|
37
|
+
*/
|
|
38
|
+
function laidOutDiagramTree(parts, frame, parse) {
|
|
39
|
+
if (!parts.layout) return void 0;
|
|
40
|
+
const data = new DiagramData(parse(parts.data));
|
|
41
|
+
const nodes = layoutDiagram(parse(parts.layout), data, frame.cx, frame.cy);
|
|
42
|
+
if (nodes.length === 0) return void 0;
|
|
43
|
+
const xml = diagramDrawingXml(nodes, frame, parts.colors ? new DiagramColors(parse(parts.colors)) : void 0, data.background);
|
|
44
|
+
for (const root of parse(new TextEncoder().encode(xml))) {
|
|
45
|
+
const found = poFindDescendant(root, "dsp:spTree");
|
|
46
|
+
if (found) return found;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { cachedDiagramTree, laidOutDiagramTree };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DiagramColors } from './colors.js';
|
|
2
|
+
import { LaidNode } from './layout-engine.js';
|
|
3
|
+
import { PoNode } from '../../po-helpers.js';
|
|
4
|
+
/**
|
|
5
|
+
* A `dsp:drawing` for boxes the engine laid out.
|
|
6
|
+
*
|
|
7
|
+
* @param nodes The laid-out boxes, in the diagram's own EMU frame.
|
|
8
|
+
* @param frame The frame the slide gives the diagram.
|
|
9
|
+
* @param colors The colours part, when the file carries one.
|
|
10
|
+
* @param bg §21.4.2.4 `dgm:bg` — the fill behind the whole diagram.
|
|
11
|
+
* @returns The XML text of the drawing part.
|
|
12
|
+
*/
|
|
13
|
+
export declare function diagramDrawingXml(nodes: ReadonlyArray<LaidNode>, frame: {
|
|
14
|
+
readonly cx: number;
|
|
15
|
+
readonly cy: number;
|
|
16
|
+
}, colors?: DiagramColors, bg?: PoNode): string;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { poAttr, poChildren, poIs, poText } from "../../po-helpers.js";
|
|
2
|
+
import { pointPaint } from "./colors.js";
|
|
3
|
+
//#region src/core/drawingml/diagram/to-drawing.ts
|
|
4
|
+
var NS = "xmlns:dsp=\"http://schemas.microsoft.com/office/drawing/2008/diagram\" xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"";
|
|
5
|
+
/**
|
|
6
|
+
* A `dsp:drawing` for boxes the engine laid out.
|
|
7
|
+
*
|
|
8
|
+
* @param nodes The laid-out boxes, in the diagram's own EMU frame.
|
|
9
|
+
* @param frame The frame the slide gives the diagram.
|
|
10
|
+
* @param colors The colours part, when the file carries one.
|
|
11
|
+
* @param bg §21.4.2.4 `dgm:bg` — the fill behind the whole diagram.
|
|
12
|
+
* @returns The XML text of the drawing part.
|
|
13
|
+
*/
|
|
14
|
+
function diagramDrawingXml(nodes, frame, colors, bg) {
|
|
15
|
+
const back = pointPaint(bg).fill;
|
|
16
|
+
const panel = back === void 0 ? "" : `<dsp:sp><dsp:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="${r(frame.cx)}" cy="${r(frame.cy)}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom>${back}<a:ln><a:noFill/></a:ln></dsp:spPr><dsp:txBody><a:bodyPr/><a:lstStyle/><a:p/></dsp:txBody></dsp:sp>`;
|
|
17
|
+
const shapes = nodes.map((n) => {
|
|
18
|
+
const off = `<a:off x="${r(n.x)}" y="${r(n.y)}"/><a:ext cx="${r(n.cx)}" cy="${r(n.cy)}"/>`;
|
|
19
|
+
const own = pointPaint(n.point.spPr);
|
|
20
|
+
const paint = n.hideGeom === true ? "<a:noFill/><a:ln><a:noFill/></a:ln>" : (own.fill ?? colors?.fill(n.styleLbl, n.index) ?? (colors?.knows(n.styleLbl) === true ? "<a:noFill/>" : "<a:solidFill><a:schemeClr val=\"accent1\"/></a:solidFill>")) + (own.line ?? colors?.line(n.styleLbl, n.index) ?? "");
|
|
21
|
+
const text = colors?.textFill(n.styleLbl, n.index);
|
|
22
|
+
return `<dsp:sp><dsp:spPr><a:xfrm${n.rotation60k !== void 0 ? ` rot="${r(n.rotation60k)}"` : ""}>${off}</a:xfrm><a:prstGeom prst="${esc(n.shapeType)}"><a:avLst/></a:prstGeom>${paint}</dsp:spPr><dsp:style><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></dsp:style><dsp:txBody>${bodyXml(n, text)}</dsp:txBody></dsp:sp>`;
|
|
23
|
+
}).join("");
|
|
24
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
25
|
+
<dsp:drawing ${NS}><dsp:spTree>${`<dsp:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="${r(frame.cx)}" cy="${r(frame.cy)}"/><a:chOff x="0" y="0"/><a:chExt cx="${r(frame.cx)}" cy="${r(frame.cy)}"/></a:xfrm></dsp:grpSpPr>`}${panel}${shapes}</dsp:spTree></dsp:drawing>`;
|
|
26
|
+
}
|
|
27
|
+
function bodyXml(node, textFill) {
|
|
28
|
+
const paragraphs = [];
|
|
29
|
+
for (const p of node.point.text ? poChildren(node.point.text) : []) {
|
|
30
|
+
if (!poIs(p, "a:p")) continue;
|
|
31
|
+
let runs = "";
|
|
32
|
+
for (const r of poChildren(p)) {
|
|
33
|
+
if (poIs(r, "a:br")) {
|
|
34
|
+
runs += "<a:br/>";
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (!poIs(r, "a:r")) continue;
|
|
38
|
+
const text = poText(poChildren(r).find((c) => poIs(c, "a:t")));
|
|
39
|
+
if (text !== "") {
|
|
40
|
+
const src = poChildren(r).find((c) => poIs(c, "a:rPr"));
|
|
41
|
+
const stated = poAttr(src, "sz");
|
|
42
|
+
const sz = stated !== void 0 ? ` sz="${esc(stated)}"` : node.fontSizePt === void 0 ? "" : ` sz="${Math.round(node.fontSizePt * 100)}"`;
|
|
43
|
+
const emph = [
|
|
44
|
+
"b",
|
|
45
|
+
"i",
|
|
46
|
+
"u"
|
|
47
|
+
].map((a) => {
|
|
48
|
+
const v = poAttr(src, a);
|
|
49
|
+
return v === void 0 ? "" : ` ${a}="${esc(v)}"`;
|
|
50
|
+
}).join("");
|
|
51
|
+
const rPr = textFill === void 0 ? `<a:rPr lang="en-US"${sz}${emph}/>` : `<a:rPr lang="en-US"${sz}${emph}>${textFill}</a:rPr>`;
|
|
52
|
+
runs += `<a:r>${rPr}<a:t>${esc(text)}</a:t></a:r>`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (runs !== "") paragraphs.push(`<a:p>${paraPr(node, p)}${runs}</a:p>`);
|
|
56
|
+
}
|
|
57
|
+
const body = `<a:bodyPr anchor="${node.anchor === void 0 ? "ctr" : esc(node.anchor)}"${node.bulleted === true ? " anchorCtr=\"0\"" : ""}><a:normAutofit/></a:bodyPr><a:lstStyle/>`;
|
|
58
|
+
return paragraphs.length > 0 ? body + paragraphs.join("") : `${body}<a:p/>`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* One paragraph's properties. `bulletEnabled` on a layout node says only that
|
|
62
|
+
* bullets are ALLOWED here; which bullet a paragraph actually takes — or that it
|
|
63
|
+
* takes none — is the data part's to state, and smartart-missing-bullet is a
|
|
64
|
+
* file of exactly two paragraphs, one `a:buNone` and one `a:buChar`, that came
|
|
65
|
+
* out with the same marker on both. So a paragraph that states its own bullet or
|
|
66
|
+
* its own alignment keeps them, and only one that states neither falls back to
|
|
67
|
+
* the layout's answer: ranged left behind a bullet where the layout allows one,
|
|
68
|
+
* centred where it does not.
|
|
69
|
+
*/
|
|
70
|
+
function paraPr(node, para) {
|
|
71
|
+
const src = poChildren(para).find((c) => poIs(c, "a:pPr"));
|
|
72
|
+
const bullet = poChildren(src).find((c) => poIs(c, "a:buNone") || poIs(c, "a:buChar") || poIs(c, "a:buAutoNum"));
|
|
73
|
+
const listed = bullet === void 0 ? node.bulleted === true : !poIs(bullet, "a:buNone");
|
|
74
|
+
const algn = poAttr(src, "algn") ?? node.align ?? (listed ? "l" : "ctr");
|
|
75
|
+
if (!listed) return `<a:pPr algn="${esc(algn)}"/>`;
|
|
76
|
+
const marL = poAttr(src, "marL") ?? "171450";
|
|
77
|
+
const indent = poAttr(src, "indent") ?? "-171450";
|
|
78
|
+
const char = bullet !== void 0 && poIs(bullet, "a:buChar") ? poAttr(bullet, "char") : void 0;
|
|
79
|
+
return `<a:pPr algn="${esc(algn)}" marL="${esc(marL)}" indent="${esc(indent)}"><a:buChar char="${esc(char ?? "•")}"/></a:pPr>`;
|
|
80
|
+
}
|
|
81
|
+
var r = (v) => Math.round(v);
|
|
82
|
+
function esc(s) {
|
|
83
|
+
return s.replace(/&/gu, "&").replace(/</gu, "<").replace(/>/gu, ">").replace(/"/gu, """);
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { diagramDrawingXml };
|
|
@@ -75,6 +75,94 @@ function presetPaths(preset, w, h, adjust) {
|
|
|
75
75
|
])];
|
|
76
76
|
}
|
|
77
77
|
case "pentagon": return [regularPolygon(w, h, 5)];
|
|
78
|
+
case "heptagon": return [regularPolygon(w, h, 7)];
|
|
79
|
+
case "octagon": return [regularPolygon(w, h, 8, Math.PI / 8)];
|
|
80
|
+
case "decagon": return [regularPolygon(w, h, 10, Math.PI / 10)];
|
|
81
|
+
case "dodecagon": return [regularPolygon(w, h, 12, Math.PI / 12)];
|
|
82
|
+
case "donut": {
|
|
83
|
+
const t = clamp(frac(adjust, "adj", 25e3), 0, .5) * Math.min(w, h);
|
|
84
|
+
const b = new PathBuilder().append(ellipseSegments(w, h));
|
|
85
|
+
const [ix, iy] = [w / 2 - t, h / 2 - t];
|
|
86
|
+
if (ix > 0 && iy > 0) {
|
|
87
|
+
b.moveTo(w / 2 + ix, h / 2).append(arcToBeziers(w / 2, h / 2, ix, iy, 0, 2 * Math.PI));
|
|
88
|
+
b.close();
|
|
89
|
+
}
|
|
90
|
+
return [b.build("evenodd")];
|
|
91
|
+
}
|
|
92
|
+
case "frame": {
|
|
93
|
+
const t = clamp(frac(adjust, "adj", 12500), 0, .5) * Math.min(w, h);
|
|
94
|
+
return [new PathBuilder().moveTo(0, 0).lineTo(w, 0).lineTo(w, h).lineTo(0, h).close().moveTo(t, t).lineTo(w - t, t).lineTo(w - t, h - t).lineTo(t, h - t).close().build("evenodd")];
|
|
95
|
+
}
|
|
96
|
+
case "diagStripe": {
|
|
97
|
+
const a = clamp(frac(adjust, "adj", 5e4), 0, 1);
|
|
98
|
+
return [polygon([
|
|
99
|
+
[0, h - h * a],
|
|
100
|
+
[w * a, h],
|
|
101
|
+
[w, h],
|
|
102
|
+
[0, 0]
|
|
103
|
+
])];
|
|
104
|
+
}
|
|
105
|
+
case "teardrop": {
|
|
106
|
+
const a = clamp(frac(adjust, "adj", 1e5), 0, 2);
|
|
107
|
+
const [rx, ry] = [w / 2, h / 2];
|
|
108
|
+
return [new PathBuilder().moveTo(rx, h).append(arcToBeziers(rx, ry, rx, ry, Math.PI / 2, 3 * Math.PI / 2)).lineTo(w * (.5 + a / 2), h * (.5 + a / 2)).close().build()];
|
|
109
|
+
}
|
|
110
|
+
case "can": return cylinder(w, h, clamp(frac(adjust, "adj", 25e3), 0, .5) * h / 2);
|
|
111
|
+
case "halfFrame": {
|
|
112
|
+
const ss = Math.min(w, h);
|
|
113
|
+
const x1 = clamp(frac(adjust, "adj2", 33333), 0, 1) * ss;
|
|
114
|
+
const y1 = clamp(frac(adjust, "adj1", 33333), 0, 1) * ss;
|
|
115
|
+
const x2 = w - (h === 0 ? 0 : y1 * w / h);
|
|
116
|
+
const y2 = h - (w === 0 ? 0 : x1 * h / w);
|
|
117
|
+
return [polygon([
|
|
118
|
+
[0, 0],
|
|
119
|
+
[0, h],
|
|
120
|
+
[w, h],
|
|
121
|
+
[x2, h - y1],
|
|
122
|
+
[x1, h - y1],
|
|
123
|
+
[x1, h - y2]
|
|
124
|
+
])];
|
|
125
|
+
}
|
|
126
|
+
case "bevel": {
|
|
127
|
+
const t = clamp(frac(adjust, "adj", 12500), 0, .5) * Math.min(w, h);
|
|
128
|
+
const face = (pts) => polygon(pts);
|
|
129
|
+
return [
|
|
130
|
+
face([
|
|
131
|
+
[0, h],
|
|
132
|
+
[w, h],
|
|
133
|
+
[w - t, h - t],
|
|
134
|
+
[t, h - t]
|
|
135
|
+
]),
|
|
136
|
+
face([
|
|
137
|
+
[0, h],
|
|
138
|
+
[t, h - t],
|
|
139
|
+
[t, t],
|
|
140
|
+
[0, 0]
|
|
141
|
+
]),
|
|
142
|
+
face([
|
|
143
|
+
[w, 0],
|
|
144
|
+
[0, 0],
|
|
145
|
+
[t, t],
|
|
146
|
+
[w - t, t]
|
|
147
|
+
]),
|
|
148
|
+
face([
|
|
149
|
+
[w, 0],
|
|
150
|
+
[w - t, t],
|
|
151
|
+
[w - t, h - t],
|
|
152
|
+
[w, h]
|
|
153
|
+
]),
|
|
154
|
+
polygon([
|
|
155
|
+
[t, t],
|
|
156
|
+
[w - t, t],
|
|
157
|
+
[w - t, h - t],
|
|
158
|
+
[t, h - t]
|
|
159
|
+
])
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
case "plaque": {
|
|
163
|
+
const t = clamp(frac(adjust, "adj", 16667), 0, .5) * Math.min(w, h);
|
|
164
|
+
return [new PathBuilder().moveTo(t, 0).lineTo(w - t, 0).append(arcToBeziers(w, 0, t, t, Math.PI, -Math.PI / 2)).lineTo(w, h - t).append(arcToBeziers(w, h, t, t, 3 * Math.PI / 2, -Math.PI / 2)).lineTo(t, h).append(arcToBeziers(0, h, t, t, 0, -Math.PI / 2)).lineTo(0, t).append(arcToBeziers(0, 0, t, t, Math.PI / 2, -Math.PI / 2)).close().build()];
|
|
165
|
+
}
|
|
78
166
|
case "hexagon": {
|
|
79
167
|
const inset = clamp(frac(adjust, "adj", 25e3) * w, 0, w / 2);
|
|
80
168
|
return [polygon([
|
|
@@ -227,6 +315,7 @@ function presetPaths(preset, w, h, adjust) {
|
|
|
227
315
|
[0, h]
|
|
228
316
|
])];
|
|
229
317
|
}
|
|
318
|
+
case "pieWedge": return [new PathBuilder().moveTo(0, 0).append(arcToBeziers(w, 0, w, h, Math.PI, -Math.PI / 2)).lineTo(w, 0).close().build()];
|
|
230
319
|
case "pie":
|
|
231
320
|
case "blockArc": {
|
|
232
321
|
const [rx, ry] = [w / 2, h / 2];
|
|
@@ -306,10 +395,8 @@ function presetPaths(preset, w, h, adjust) {
|
|
|
306
395
|
[w / 2, h]
|
|
307
396
|
])];
|
|
308
397
|
case "flowChartDelay": return [new PathBuilder().moveTo(0, 0).lineTo(w / 2, 0).append(arcToBeziers(w / 2, h / 2, w / 2, h / 2, -Math.PI / 2, Math.PI)).lineTo(0, h).close().build()];
|
|
309
|
-
case "flowChartMagneticDisk":
|
|
310
|
-
|
|
311
|
-
return [new PathBuilder().moveTo(0, h - ry).append(arcToBeziers(w / 2, h - ry, w / 2, ry, Math.PI, -2 * Math.PI)).moveTo(0, h - ry).lineTo(0, ry).append(arcToBeziers(w / 2, ry, w / 2, ry, Math.PI, -Math.PI)).lineTo(w, h - ry).build()];
|
|
312
|
-
}
|
|
398
|
+
case "flowChartMagneticDisk": return cylinder(w, h, h / 6);
|
|
399
|
+
case "flowChartMagneticDrum": return drum(w, h, w / 6);
|
|
313
400
|
case "flowChartMagneticTape": {
|
|
314
401
|
const foot = h / 8;
|
|
315
402
|
return [{ segments: ellipseSegments(w, h) }, polygon([
|
|
@@ -626,14 +713,37 @@ function star(w, h, preset, adjust) {
|
|
|
626
713
|
}
|
|
627
714
|
return polygon(pts);
|
|
628
715
|
}
|
|
629
|
-
|
|
716
|
+
/**
|
|
717
|
+
* A cylinder standing on its base: the body under its lid, and the lid drawn
|
|
718
|
+
* again on top so its near edge shows.
|
|
719
|
+
*
|
|
720
|
+
* Both paths are wound the SAME way round. Wound against each other a nonzero
|
|
721
|
+
* fill cancels the two and the top comes out hollow, which is how the flowchart
|
|
722
|
+
* disk of tdf114848's fifth page had been drawn all along; and the base bulges
|
|
723
|
+
* DOWN, which the same shape had going up.
|
|
724
|
+
*/
|
|
725
|
+
function cylinder(w, h, ry) {
|
|
726
|
+
const [rx, cx] = [w / 2, w / 2];
|
|
727
|
+
return [new PathBuilder().moveTo(0, ry).lineTo(0, h - ry).append(arcToBeziers(cx, h - ry, rx, ry, Math.PI, -Math.PI)).lineTo(w, ry).append(arcToBeziers(cx, ry, rx, ry, 0, -Math.PI)).close().build(), new PathBuilder().moveTo(w, h - ry).append(arcToBeziers(cx, h - ry, rx, ry, 0, -2 * Math.PI)).close().build()];
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* A cylinder lying on its side: the body with a rounded end at each side, and
|
|
731
|
+
* the near cap drawn again over the right one. Wound like {@link cylinder}, and
|
|
732
|
+
* for the same reason — the two paths must turn the same way or a nonzero fill
|
|
733
|
+
* cancels them.
|
|
734
|
+
*/
|
|
735
|
+
function drum(w, h, rx) {
|
|
736
|
+
const [ry, cy] = [h / 2, h / 2];
|
|
737
|
+
return [new PathBuilder().moveTo(w - rx, h).lineTo(rx, h).append(arcToBeziers(rx, cy, rx, ry, Math.PI / 2, Math.PI)).lineTo(w - rx, 0).append(arcToBeziers(w - rx, cy, rx, ry, -Math.PI / 2, Math.PI)).close().build(), new PathBuilder().moveTo(w, cy).append(arcToBeziers(w - rx, cy, rx, ry, 0, 2 * Math.PI)).close().build()];
|
|
738
|
+
}
|
|
739
|
+
function regularPolygon(w, h, n, turn = 0) {
|
|
630
740
|
const cx = w / 2;
|
|
631
741
|
const cy = h / 2;
|
|
632
742
|
const rx = w / 2;
|
|
633
743
|
const ry = h / 2;
|
|
634
744
|
const pts = [];
|
|
635
745
|
for (let i = 0; i < n; i++) {
|
|
636
|
-
const a = Math.PI / 2 + i * 2 * Math.PI / n;
|
|
746
|
+
const a = Math.PI / 2 + turn + i * 2 * Math.PI / n;
|
|
637
747
|
pts.push([cx + rx * Math.cos(a), cy + ry * Math.sin(a)]);
|
|
638
748
|
}
|
|
639
749
|
return polygon(pts);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** The two edges of a warp at one horizontal position, `0`…`1` down the box. */
|
|
2
|
+
export interface WarpEdges {
|
|
3
|
+
readonly top: number;
|
|
4
|
+
readonly bottom: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Whether a preset bends text at all. `textNoShape` is the "no warp" member of
|
|
8
|
+
* the enumeration and by far its most common value — two thirds of the decks
|
|
9
|
+
* that mention a warp state only this one — and a body carrying it is an
|
|
10
|
+
* ordinary text box, NOT WordArt stretched to its shape.
|
|
11
|
+
*
|
|
12
|
+
* @param preset The `a:prstTxWarp @prst` value.
|
|
13
|
+
* @returns Whether {@link textWarpEdges} can bend text through this preset.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isTextWarp(preset: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Where a warped body's two frames sit on the page: the shape's box, which the
|
|
18
|
+
* warped text is stretched onto, and the box the UN-warped block occupies.
|
|
19
|
+
* Both are in the page's top-left frame, y growing down.
|
|
20
|
+
*/
|
|
21
|
+
export interface WarpFrame {
|
|
22
|
+
readonly preset: string;
|
|
23
|
+
readonly adjust?: number;
|
|
24
|
+
readonly boxX: number;
|
|
25
|
+
readonly boxY: number;
|
|
26
|
+
readonly boxWidth: number;
|
|
27
|
+
readonly boxHeight: number;
|
|
28
|
+
readonly srcX: number;
|
|
29
|
+
readonly srcWidth: number;
|
|
30
|
+
readonly srcTop: number;
|
|
31
|
+
readonly srcHeight: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The matrix that places one glyph of a warped body.
|
|
35
|
+
*
|
|
36
|
+
* Maps the glyph's own text space — x along its advance, y UP from its
|
|
37
|
+
* baseline — into the page's top-left frame, as `[a, b, c, d, e, f]` with
|
|
38
|
+
* `px = a·x + c·y + e` and `py = b·x + d·y + f`. Upright text therefore has a
|
|
39
|
+
* negative `d`: the glyph's y runs against the page's.
|
|
40
|
+
*
|
|
41
|
+
* @param frame The two frames, from the laid-out line.
|
|
42
|
+
* @param glyphX The glyph's left edge in the un-warped block.
|
|
43
|
+
* @param advance How wide the glyph is there.
|
|
44
|
+
* @param baselineY The line's baseline in the un-warped block.
|
|
45
|
+
* @returns The six numbers, or `undefined` where the warp leaves no room to
|
|
46
|
+
* draw — the pinched end of a fade, or a preset this file cannot bend.
|
|
47
|
+
*/
|
|
48
|
+
export declare function warpGlyphMatrix(frame: WarpFrame, glyphX: number, advance: number, baselineY: number): readonly [number, number, number, number, number, number] | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The two edges of a warp at one position across its box.
|
|
51
|
+
*
|
|
52
|
+
* @param preset The `a:prstTxWarp @prst` value.
|
|
53
|
+
* @param u Position across the box, `0` at its left edge and `1` at its right.
|
|
54
|
+
* @param adj The `a:avLst` `adj` guide in hundred-thousandths, when the file states one.
|
|
55
|
+
* @returns The top and bottom edges, `0`…`1` down the box, or `undefined` for a
|
|
56
|
+
* preset this file does not bend (an unknown name, or `textNoShape`).
|
|
57
|
+
*/
|
|
58
|
+
export declare function textWarpEdges(preset: string, u: number, adj?: number): WarpEdges | undefined;
|