manga-renderer 1.0.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.
Files changed (148) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +118 -0
  3. package/dist/index.d.ts +28 -0
  4. package/dist/index.js +184 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/book/book.d.ts +133 -0
  7. package/dist/lib/book/book.js +329 -0
  8. package/dist/lib/book/book.js.map +1 -0
  9. package/dist/lib/book/envelope.d.ts +26 -0
  10. package/dist/lib/book/envelope.js +158 -0
  11. package/dist/lib/book/envelope.js.map +1 -0
  12. package/dist/lib/book/imagePacking.d.ts +10 -0
  13. package/dist/lib/book/imagePacking.js +213 -0
  14. package/dist/lib/book/imagePacking.js.map +1 -0
  15. package/dist/lib/book/layout.d.ts +41 -0
  16. package/dist/lib/book/layout.js +14 -0
  17. package/dist/lib/book/layout.js.map +1 -0
  18. package/dist/lib/book/notebook.d.ts +72 -0
  19. package/dist/lib/book/notebook.js +30 -0
  20. package/dist/lib/book/notebook.js.map +1 -0
  21. package/dist/lib/book/richChat.d.ts +36 -0
  22. package/dist/lib/book/richChat.js +87 -0
  23. package/dist/lib/book/richChat.js.map +1 -0
  24. package/dist/lib/book/storyboard.d.ts +125 -0
  25. package/dist/lib/book/storyboard.js +44 -0
  26. package/dist/lib/book/storyboard.js.map +1 -0
  27. package/dist/lib/layeredCanvas/dataModels/bubble.d.ts +96 -0
  28. package/dist/lib/layeredCanvas/dataModels/bubble.js +630 -0
  29. package/dist/lib/layeredCanvas/dataModels/bubble.js.map +1 -0
  30. package/dist/lib/layeredCanvas/dataModels/effect.d.ts +25 -0
  31. package/dist/lib/layeredCanvas/dataModels/effect.js +104 -0
  32. package/dist/lib/layeredCanvas/dataModels/effect.js.map +1 -0
  33. package/dist/lib/layeredCanvas/dataModels/film.d.ts +44 -0
  34. package/dist/lib/layeredCanvas/dataModels/film.js +172 -0
  35. package/dist/lib/layeredCanvas/dataModels/film.js.map +1 -0
  36. package/dist/lib/layeredCanvas/dataModels/frameTree.d.ts +99 -0
  37. package/dist/lib/layeredCanvas/dataModels/frameTree.js +861 -0
  38. package/dist/lib/layeredCanvas/dataModels/frameTree.js.map +1 -0
  39. package/dist/lib/layeredCanvas/dataModels/media.d.ts +39 -0
  40. package/dist/lib/layeredCanvas/dataModels/media.js +69 -0
  41. package/dist/lib/layeredCanvas/dataModels/media.js.map +1 -0
  42. package/dist/lib/layeredCanvas/layers/SampleLayer.d.ts +6 -0
  43. package/dist/lib/layeredCanvas/layers/SampleLayer.js +22 -0
  44. package/dist/lib/layeredCanvas/layers/SampleLayer.js.map +1 -0
  45. package/dist/lib/layeredCanvas/layers/arrayLayer.d.ts +49 -0
  46. package/dist/lib/layeredCanvas/layers/arrayLayer.js +364 -0
  47. package/dist/lib/layeredCanvas/layers/arrayLayer.js.map +1 -0
  48. package/dist/lib/layeredCanvas/layers/bubbleLayer.d.ts +97 -0
  49. package/dist/lib/layeredCanvas/layers/bubbleLayer.js +1418 -0
  50. package/dist/lib/layeredCanvas/layers/bubbleLayer.js.map +1 -0
  51. package/dist/lib/layeredCanvas/layers/floorLayer.d.ts +13 -0
  52. package/dist/lib/layeredCanvas/layers/floorLayer.js +64 -0
  53. package/dist/lib/layeredCanvas/layers/floorLayer.js.map +1 -0
  54. package/dist/lib/layeredCanvas/layers/frameLayer.d.ts +106 -0
  55. package/dist/lib/layeredCanvas/layers/frameLayer.js +1283 -0
  56. package/dist/lib/layeredCanvas/layers/frameLayer.js.map +1 -0
  57. package/dist/lib/layeredCanvas/layers/inlinePainterLayer.d.ts +33 -0
  58. package/dist/lib/layeredCanvas/layers/inlinePainterLayer.js +222 -0
  59. package/dist/lib/layeredCanvas/layers/inlinePainterLayer.js.map +1 -0
  60. package/dist/lib/layeredCanvas/layers/paperRendererLayer.d.ts +64 -0
  61. package/dist/lib/layeredCanvas/layers/paperRendererLayer.js +443 -0
  62. package/dist/lib/layeredCanvas/layers/paperRendererLayer.js.map +1 -0
  63. package/dist/lib/layeredCanvas/layers/undoLayer.d.ts +8 -0
  64. package/dist/lib/layeredCanvas/layers/undoLayer.js +24 -0
  65. package/dist/lib/layeredCanvas/layers/undoLayer.js.map +1 -0
  66. package/dist/lib/layeredCanvas/system/keyCache.d.ts +4 -0
  67. package/dist/lib/layeredCanvas/system/keyCache.js +61 -0
  68. package/dist/lib/layeredCanvas/system/keyCache.js.map +1 -0
  69. package/dist/lib/layeredCanvas/system/layeredCanvas.d.ts +172 -0
  70. package/dist/lib/layeredCanvas/system/layeredCanvas.js +597 -0
  71. package/dist/lib/layeredCanvas/system/layeredCanvas.js.map +1 -0
  72. package/dist/lib/layeredCanvas/system/paperArray.d.ts +29 -0
  73. package/dist/lib/layeredCanvas/system/paperArray.js +108 -0
  74. package/dist/lib/layeredCanvas/system/paperArray.js.map +1 -0
  75. package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.d.ts +7 -0
  76. package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.js +728 -0
  77. package/dist/lib/layeredCanvas/tools/draw/bubbleGraphic.js.map +1 -0
  78. package/dist/lib/layeredCanvas/tools/draw/clickableIcon.d.ts +42 -0
  79. package/dist/lib/layeredCanvas/tools/draw/clickableIcon.js +129 -0
  80. package/dist/lib/layeredCanvas/tools/draw/clickableIcon.js.map +1 -0
  81. package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.d.ts +4 -0
  82. package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.js +53 -0
  83. package/dist/lib/layeredCanvas/tools/draw/drawFilmStack.js.map +1 -0
  84. package/dist/lib/layeredCanvas/tools/draw/drawText.d.ts +8 -0
  85. package/dist/lib/layeredCanvas/tools/draw/drawText.js +45 -0
  86. package/dist/lib/layeredCanvas/tools/draw/drawText.js.map +1 -0
  87. package/dist/lib/layeredCanvas/tools/draw/richText.d.ts +15 -0
  88. package/dist/lib/layeredCanvas/tools/draw/richText.js +172 -0
  89. package/dist/lib/layeredCanvas/tools/draw/richText.js.map +1 -0
  90. package/dist/lib/layeredCanvas/tools/draw/selectionFrame.d.ts +5 -0
  91. package/dist/lib/layeredCanvas/tools/draw/selectionFrame.js +63 -0
  92. package/dist/lib/layeredCanvas/tools/draw/selectionFrame.js.map +1 -0
  93. package/dist/lib/layeredCanvas/tools/draw/typeSetting.d.ts +16 -0
  94. package/dist/lib/layeredCanvas/tools/draw/typeSetting.js +2 -0
  95. package/dist/lib/layeredCanvas/tools/draw/typeSetting.js.map +1 -0
  96. package/dist/lib/layeredCanvas/tools/draw/verticalText.d.ts +3 -0
  97. package/dist/lib/layeredCanvas/tools/draw/verticalText.js +230 -0
  98. package/dist/lib/layeredCanvas/tools/draw/verticalText.js.map +1 -0
  99. package/dist/lib/layeredCanvas/tools/focusKeeper.d.ts +8 -0
  100. package/dist/lib/layeredCanvas/tools/focusKeeper.js +15 -0
  101. package/dist/lib/layeredCanvas/tools/focusKeeper.js.map +1 -0
  102. package/dist/lib/layeredCanvas/tools/frameExamples.d.ts +382 -0
  103. package/dist/lib/layeredCanvas/tools/frameExamples.js +758 -0
  104. package/dist/lib/layeredCanvas/tools/frameExamples.js.map +1 -0
  105. package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.d.ts +12 -0
  106. package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.js +117 -0
  107. package/dist/lib/layeredCanvas/tools/geometry/bubbleGeometry.js.map +1 -0
  108. package/dist/lib/layeredCanvas/tools/geometry/convertPoint.d.ts +2 -0
  109. package/dist/lib/layeredCanvas/tools/geometry/convertPoint.js +25 -0
  110. package/dist/lib/layeredCanvas/tools/geometry/convertPoint.js.map +1 -0
  111. package/dist/lib/layeredCanvas/tools/geometry/geometry.d.ts +69 -0
  112. package/dist/lib/layeredCanvas/tools/geometry/geometry.js +408 -0
  113. package/dist/lib/layeredCanvas/tools/geometry/geometry.js.map +1 -0
  114. package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.d.ts +1 -0
  115. package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.js +58 -0
  116. package/dist/lib/layeredCanvas/tools/geometry/geometry.vitest.js.map +1 -0
  117. package/dist/lib/layeredCanvas/tools/geometry/quickHull.d.ts +10 -0
  118. package/dist/lib/layeredCanvas/tools/geometry/quickHull.js +91 -0
  119. package/dist/lib/layeredCanvas/tools/geometry/quickHull.js.map +1 -0
  120. package/dist/lib/layeredCanvas/tools/geometry/trapezoid.d.ts +18 -0
  121. package/dist/lib/layeredCanvas/tools/geometry/trapezoid.js +105 -0
  122. package/dist/lib/layeredCanvas/tools/geometry/trapezoid.js.map +1 -0
  123. package/dist/lib/layeredCanvas/tools/grid.d.ts +7 -0
  124. package/dist/lib/layeredCanvas/tools/grid.js +16 -0
  125. package/dist/lib/layeredCanvas/tools/grid.js.map +1 -0
  126. package/dist/lib/layeredCanvas/tools/haiku.d.ts +1 -0
  127. package/dist/lib/layeredCanvas/tools/haiku.js +17 -0
  128. package/dist/lib/layeredCanvas/tools/haiku.js.map +1 -0
  129. package/dist/lib/layeredCanvas/tools/imageUtil.d.ts +8 -0
  130. package/dist/lib/layeredCanvas/tools/imageUtil.js +58 -0
  131. package/dist/lib/layeredCanvas/tools/imageUtil.js.map +1 -0
  132. package/dist/lib/layeredCanvas/tools/kinsoku.d.ts +26 -0
  133. package/dist/lib/layeredCanvas/tools/kinsoku.js +124 -0
  134. package/dist/lib/layeredCanvas/tools/kinsoku.js.map +1 -0
  135. package/dist/lib/layeredCanvas/tools/misc.d.ts +25 -0
  136. package/dist/lib/layeredCanvas/tools/misc.js +46 -0
  137. package/dist/lib/layeredCanvas/tools/misc.js.map +1 -0
  138. package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.d.ts +2 -0
  139. package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.js +21 -0
  140. package/dist/lib/layeredCanvas/tools/perfectFreehandUtil.js.map +1 -0
  141. package/dist/lib/layeredCanvas/tools/pictureControl.d.ts +4 -0
  142. package/dist/lib/layeredCanvas/tools/pictureControl.js +24 -0
  143. package/dist/lib/layeredCanvas/tools/pictureControl.js.map +1 -0
  144. package/dist/lib/layeredCanvas/tools/rectHandle.d.ts +6 -0
  145. package/dist/lib/layeredCanvas/tools/rectHandle.js +17 -0
  146. package/dist/lib/layeredCanvas/tools/rectHandle.js.map +1 -0
  147. package/dist/tsconfig.tsbuildinfo +1 -0
  148. package/package.json +64 -0
@@ -0,0 +1,861 @@
1
+ import { lineIntersection, line, line2, deg2rad, isVectorZero, add2D, computeConstraintedRect, getRectCenter, translateRect } from "../tools/geometry/geometry";
2
+ import { trapezoidBoundingRect, isPointInTrapezoid, extendTrapezoid, pointToQuadrilateralDistance } from "../tools/geometry/trapezoid";
3
+ import { rectHandles } from "../tools/rectHandle";
4
+ import { FilmStack, calculateMinimumBoundingRect } from "./film";
5
+ export class FrameElement {
6
+ rawSize;
7
+ direction;
8
+ children;
9
+ localLength; // 主軸サイズ
10
+ localBreadth; // 交差軸サイズ
11
+ divider;
12
+ cornerOffsets;
13
+ bgColor;
14
+ borderColor;
15
+ borderWidth;
16
+ z;
17
+ visibility;
18
+ semantics;
19
+ prompt;
20
+ pseudo; // 4コマタイトルなどの擬似要素、流し込みやバッチ処理のときに無視する
21
+ filmStack;
22
+ // 以下は揮発性
23
+ gallery;
24
+ focused;
25
+ residenceTime;
26
+ constructor(size) {
27
+ // 保持するのは兄弟間でのみ有効な相対サイズ(ローカル座標)
28
+ // 絶対座標はレンダリング時に算出する
29
+ this.rawSize = size;
30
+ this.direction = null;
31
+ this.children = [];
32
+ this.localLength = 0;
33
+ this.localBreadth = 0;
34
+ this.divider = { spacing: 0, slant: 0 };
35
+ this.cornerOffsets = { topLeft: [0, 0], topRight: [0, 0], bottomLeft: [0, 0], bottomRight: [0, 0] };
36
+ this.bgColor = null;
37
+ this.borderColor = null;
38
+ this.borderWidth = null;
39
+ this.z = 0;
40
+ this.visibility = 2;
41
+ this.prompt = ["1 dog", "1 cat", "1 rabbit", "1 elephant", "1 dolphin", "1 bird"][Math.floor(Math.random() * 6)];
42
+ this.pseudo = false;
43
+ this.semantics = null;
44
+ // リーフ要素の場合は絵がある可能性がある
45
+ this.filmStack = new FilmStack();
46
+ // 以下揮発性
47
+ this.gallery = [];
48
+ this.focused = false;
49
+ this.residenceTime = 0;
50
+ }
51
+ clone() {
52
+ const element = new FrameElement(this.rawSize);
53
+ element.direction = this.direction;
54
+ element.children = this.children.map(child => child.clone());
55
+ element.localLength = this.localLength;
56
+ element.localBreadth = this.localBreadth;
57
+ element.divider = { ...this.divider };
58
+ element.cornerOffsets = {
59
+ topLeft: [...this.cornerOffsets.topLeft],
60
+ topRight: [...this.cornerOffsets.topRight],
61
+ bottomLeft: [...this.cornerOffsets.bottomLeft],
62
+ bottomRight: [...this.cornerOffsets.bottomRight],
63
+ };
64
+ element.bgColor = this.bgColor;
65
+ element.borderColor = this.borderColor;
66
+ element.borderWidth = this.borderWidth;
67
+ element.z = this.z;
68
+ element.visibility = this.visibility;
69
+ element.semantics = this.semantics;
70
+ element.prompt = this.prompt;
71
+ element.filmStack = new FilmStack();
72
+ element.filmStack.films = this.filmStack.films.map(film => film.clone());
73
+ element.residenceTime = this.residenceTime;
74
+ return element;
75
+ }
76
+ static compile(markUp) {
77
+ const element = FrameElement.compileNode(markUp);
78
+ const children = markUp.column || markUp.row;
79
+ if (children) {
80
+ element.direction = markUp.column ? 'v' : 'h';
81
+ element.children = children.map((child) => this.compile(child));
82
+ element.calculateLengthAndBreadth();
83
+ }
84
+ return element;
85
+ }
86
+ static compileNode(markUp) {
87
+ const element = new FrameElement(markUp.width ?? markUp.height ?? markUp.size ?? 1);
88
+ element.divider = {
89
+ spacing: markUp.divider?.spacing ?? 0,
90
+ slant: markUp.divider?.slant ?? 0
91
+ };
92
+ if (markUp.padding) {
93
+ const l = markUp.padding.left ?? 0;
94
+ const t = markUp.padding.top ?? 0;
95
+ const r = markUp.padding.right ?? 0;
96
+ const b = markUp.padding.bottom ?? 0;
97
+ element.cornerOffsets = {
98
+ topLeft: [l, t],
99
+ topRight: [r, t],
100
+ bottomLeft: [l, b],
101
+ bottomRight: [r, b],
102
+ };
103
+ }
104
+ else if (markUp.cornerOffsets) {
105
+ element.cornerOffsets = {
106
+ topLeft: markUp.cornerOffsets.topLeft ?? [0, 0],
107
+ topRight: markUp.cornerOffsets.topRight ?? [0, 0],
108
+ bottomLeft: markUp.cornerOffsets.bottomLeft ?? [0, 0],
109
+ bottomRight: markUp.cornerOffsets.bottomRight ?? [0, 0]
110
+ };
111
+ }
112
+ else {
113
+ element.cornerOffsets = { topLeft: [0, 0], topRight: [0, 0], bottomLeft: [0, 0], bottomRight: [0, 0] };
114
+ }
115
+ element.bgColor = markUp.bgColor;
116
+ element.borderColor = markUp.borderColor;
117
+ element.borderWidth = markUp.borderWidth;
118
+ element.z = markUp.z ?? 0;
119
+ element.visibility = markUp.visibility ?? 2;
120
+ element.semantics = markUp.semantics;
121
+ element.prompt = markUp.prompt ?? ["1 dog", "1 cat", "1 rabbit", "1 elephant", "1 dolphin", "1 bird"][Math.floor(Math.random() * 6)];
122
+ element.pseudo = markUp.pseudo ?? false;
123
+ return element;
124
+ }
125
+ static decompile(element) {
126
+ return this.decompileAux(element, 'v');
127
+ }
128
+ static decompileAux(element, parentDir) {
129
+ const markUpElement = this.decompileNode(element, parentDir);
130
+ if (element.direction) {
131
+ const dir = element.direction == 'h' ? 'row' : 'column';
132
+ markUpElement[dir] = [];
133
+ for (let i = 0; i < element.children.length; i++) {
134
+ markUpElement[dir].push(this.decompileAux(element.children[i], element.direction));
135
+ }
136
+ }
137
+ return markUpElement;
138
+ }
139
+ static decompileNode(element, parentDir) {
140
+ function cleanCornerOffsets(co) {
141
+ const m = {
142
+ topLeft: isVectorZero(co.topLeft) ? undefined : co.topLeft,
143
+ topRight: isVectorZero(co.topRight) ? undefined : co.topRight,
144
+ bottomLeft: isVectorZero(co.bottomLeft) ? undefined : co.bottomLeft,
145
+ bottomRight: isVectorZero(co.bottomRight) ? undefined : co.bottomRight,
146
+ };
147
+ if (Object.keys(m).length === 0) {
148
+ return undefined;
149
+ }
150
+ return m;
151
+ }
152
+ const markUpElement = {};
153
+ if (element.bgColor) {
154
+ markUpElement.bgColor = element.bgColor;
155
+ }
156
+ if (element.borderColor) {
157
+ markUpElement.borderColor = element.borderColor;
158
+ }
159
+ if (element.borderWidth) {
160
+ markUpElement.borderWidth = element.borderWidth;
161
+ }
162
+ if (element.z && element.z !== 0) {
163
+ markUpElement.z = element.z;
164
+ }
165
+ if (element.visibility !== 2) {
166
+ markUpElement.visibility = element.visibility;
167
+ }
168
+ if (element.semantics) {
169
+ markUpElement.semantics = element.semantics;
170
+ }
171
+ if (element.prompt) {
172
+ markUpElement.prompt = element.prompt;
173
+ }
174
+ if (element.pseudo) {
175
+ markUpElement.pseudo = true;
176
+ }
177
+ if (element.direction) {
178
+ const dir = element.direction == 'h' ? 'row' : 'column';
179
+ markUpElement[dir] = [];
180
+ for (let i = 0; i < element.children.length; i++) {
181
+ markUpElement[dir].push(this.decompileAux(element.children[i], element.direction));
182
+ }
183
+ }
184
+ if (element.divider.spacing !== 0 || element.divider.slant !== 0) {
185
+ markUpElement.divider = {};
186
+ if (element.divider.spacing !== 0) {
187
+ markUpElement.divider.spacing = element.divider.spacing;
188
+ }
189
+ if (element.divider.slant !== 0) {
190
+ markUpElement.divider.slant = element.divider.slant;
191
+ }
192
+ }
193
+ markUpElement.cornerOffsets = cleanCornerOffsets(element.cornerOffsets);
194
+ if (parentDir == 'h') {
195
+ markUpElement.width = element.rawSize;
196
+ }
197
+ else {
198
+ markUpElement.height = element.rawSize;
199
+ }
200
+ return markUpElement;
201
+ }
202
+ static findElement(root, f) {
203
+ if (f(root)) {
204
+ return root;
205
+ }
206
+ else {
207
+ for (let i = 0; i < root.children.length; i++) {
208
+ const child = this.findElement(root.children[i], f);
209
+ if (child) {
210
+ return child;
211
+ }
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+ static findParent(root, target) {
217
+ for (let i = 0; i < root.children.length; i++) {
218
+ const child = root.children[i];
219
+ if (child == target) {
220
+ return root;
221
+ }
222
+ else {
223
+ const parent = this.findParent(child, target);
224
+ if (parent) {
225
+ return parent;
226
+ }
227
+ }
228
+ }
229
+ return null;
230
+ }
231
+ static eraseElement(root, target) {
232
+ const parent = this.findParent(root, target);
233
+ if (parent) {
234
+ if (parent.children.length === 1) {
235
+ // 兄弟がいない場合は親を削除する
236
+ this.eraseElement(root, parent);
237
+ }
238
+ else {
239
+ // 兄弟がいる場合は親から削除する
240
+ const index = parent.children.indexOf(target);
241
+ parent.children.splice(index, 1);
242
+ parent.calculateLengthAndBreadth();
243
+ }
244
+ }
245
+ // ルート要素は削除できない
246
+ }
247
+ static duplicateElement(root, target) {
248
+ console.log('duplicateElement', root, target);
249
+ const parent = this.findParent(root, target);
250
+ if (parent) {
251
+ const index = parent.children.indexOf(target);
252
+ const newElement = target.clone();
253
+ newElement.calculateLengthAndBreadth();
254
+ parent.children.splice(index + 1, 0, newElement);
255
+ parent.calculateLengthAndBreadth();
256
+ }
257
+ // ルート要素は複製できない(ことにしておく)
258
+ }
259
+ static splitElementHorizontal(root, target) {
260
+ this.splitElement(root, target, 'h');
261
+ }
262
+ static splitElementVertical(root, target) {
263
+ this.splitElement(root, target, 'v');
264
+ }
265
+ static splitElement(root, target, splitDirection) {
266
+ const parent = this.findParent(root, target);
267
+ if (parent) {
268
+ const dir = parent.direction;
269
+ console.log(dir, splitDirection);
270
+ if (dir === splitDirection) {
271
+ console.log("same direction");
272
+ const index = parent.children.indexOf(target);
273
+ const spacing = target.divider.spacing;
274
+ const length = target.rawSize;
275
+ const newElement = target.clone();
276
+ newElement.rawSize = (length - spacing) / 2;
277
+ newElement.divider = { ...target.divider };
278
+ newElement.calculateLengthAndBreadth();
279
+ target.rawSize = newElement.rawSize;
280
+ target.divider.spacing = length * 0.05;
281
+ parent.children.splice(index + 1, 0, newElement);
282
+ parent.calculateLengthAndBreadth();
283
+ }
284
+ else {
285
+ console.log("different direction");
286
+ const index = parent.children.indexOf(target);
287
+ const newElement = new FrameElement(target.rawSize);
288
+ const length = target.rawSize;
289
+ newElement.direction = splitDirection;
290
+ for (let i = 0; i < 2; i++) {
291
+ const newChild = target.clone();
292
+ newChild.calculateLengthAndBreadth();
293
+ newElement.children.push(newChild);
294
+ }
295
+ newElement.divider = { ...target.divider };
296
+ newElement.children[0].divider.spacing = length * 0.05;
297
+ newElement.calculateLengthAndBreadth();
298
+ parent.children[index] = newElement;
299
+ }
300
+ }
301
+ else {
302
+ // target === root
303
+ const newElement = root.clone();
304
+ root.children = [newElement];
305
+ root.direction = splitDirection;
306
+ this.splitElement(root, newElement, splitDirection);
307
+ }
308
+ }
309
+ static transposeDivider(root, target) {
310
+ const parent = this.findParent(root, target);
311
+ if (parent) {
312
+ const index = parent.children.indexOf(target);
313
+ const divider = parent.children[index].divider;
314
+ if (parent.children.length === 2) {
315
+ parent.direction = parent.direction === 'h' ? 'v' : 'h';
316
+ // 親の親と方向が同じなら埋め込んだほうがいい
317
+ const grandParent = this.findParent(root, parent);
318
+ if (grandParent && grandParent.direction === parent.direction) {
319
+ const grandIndex = grandParent.children.indexOf(parent);
320
+ const l = parent.rawSize;
321
+ const ll = parent.children[0].rawSize + parent.children[1].rawSize + divider.spacing;
322
+ parent.children[0].rawSize = l * parent.children[0].rawSize / ll;
323
+ parent.children[1].rawSize = l * parent.children[1].rawSize / ll;
324
+ parent.children[0].divider = { ...divider, spacing: l * divider.spacing / ll };
325
+ parent.children[1].divider = parent.divider;
326
+ grandParent.children.splice(grandIndex, 1, ...parent.children);
327
+ grandParent.calculateLengthAndBreadth();
328
+ }
329
+ }
330
+ else if (2 < parent.children.length) {
331
+ const nextSibling = parent.children[index + 1];
332
+ const size = target.rawSize + divider.spacing + nextSibling.rawSize;
333
+ const newContainer = new FrameElement(target.rawSize);
334
+ newContainer.rawSize = size;
335
+ newContainer.direction = parent.direction === 'h' ? 'v' : 'h';
336
+ newContainer.children.push(target);
337
+ newContainer.children.push(nextSibling);
338
+ newContainer.divider = { ...nextSibling.divider };
339
+ newContainer.calculateLengthAndBreadth();
340
+ parent.children.splice(index, 2, newContainer);
341
+ }
342
+ }
343
+ }
344
+ calculateLengthAndBreadth() {
345
+ let totalLength = 0;
346
+ totalLength = 0;
347
+ this.localBreadth = this.rawSize;
348
+ for (let i = 0; i < this.children.length; i++) {
349
+ const child = this.children[i];
350
+ totalLength += child.rawSize;
351
+ if (i < this.children.length - 1) {
352
+ totalLength += child.divider.spacing;
353
+ }
354
+ }
355
+ this.localLength = totalLength;
356
+ }
357
+ getLogicalSize() {
358
+ if (this.direction === 'h') {
359
+ return [this.localLength, this.localBreadth];
360
+ }
361
+ else if (this.direction === 'v') {
362
+ return [this.localBreadth, this.localLength];
363
+ }
364
+ else {
365
+ return [this.rawSize, this.rawSize];
366
+ }
367
+ }
368
+ isLeaf() {
369
+ return this.children.length === 0;
370
+ }
371
+ isAuthentic() {
372
+ return 0 < this.visibility && !this.pseudo;
373
+ }
374
+ insertElement(index) {
375
+ const parent = this;
376
+ let totalSize = 0;
377
+ for (let i = 0; i < parent.children.length; i++) {
378
+ totalSize += parent.children[i].rawSize;
379
+ }
380
+ const avgSize = totalSize / parent.children.length;
381
+ let totalDivider = 0;
382
+ for (let i = 0; i < parent.children.length - 1; i++) {
383
+ totalDivider += parent.children[i].divider.spacing;
384
+ }
385
+ const avgDivider = totalDivider / (parent.children.length - 1);
386
+ console.log("insertElement", avgSize, avgDivider);
387
+ const newElement = new FrameElement(avgSize);
388
+ newElement.divider = { spacing: avgDivider, slant: 0 };
389
+ newElement.calculateLengthAndBreadth();
390
+ parent.children.splice(index, 0, newElement);
391
+ parent.calculateLengthAndBreadth();
392
+ }
393
+ }
394
+ function paddedSquare(rawOrigin, rawSize, cornerOffsets) {
395
+ const [w, h] = rawSize;
396
+ const topLeft = [rawOrigin[0] + cornerOffsets.topLeft[0] * w, rawOrigin[1] + cornerOffsets.topLeft[1] * h];
397
+ const topRight = [rawOrigin[0] + w - cornerOffsets.topRight[0] * w, rawOrigin[1] + cornerOffsets.topRight[1] * h];
398
+ const bottomLeft = [rawOrigin[0] + cornerOffsets.bottomLeft[0] * w, rawOrigin[1] + h - cornerOffsets.bottomLeft[1] * h];
399
+ const bottomRight = [rawOrigin[0] + w - cornerOffsets.bottomRight[0] * w, rawOrigin[1] + h - cornerOffsets.bottomRight[1] * h];
400
+ const origin = [Math.min(topLeft[0], bottomLeft[0]), Math.min(topLeft[1], topRight[1])];
401
+ const size = [Math.max(topRight[0], bottomRight[0]) - origin[0], Math.max(bottomLeft[1], bottomRight[1]) - origin[1]];
402
+ return [origin, size];
403
+ }
404
+ export function calculatePhysicalLayout(element, rawSize, rawOrigin) {
405
+ const [origin, size] = paddedSquare(rawOrigin, rawSize, element.cornerOffsets);
406
+ const corners = {
407
+ topLeft: [origin[0], origin[1]],
408
+ topRight: [origin[0] + size[0], origin[1]],
409
+ bottomLeft: [origin[0], origin[1] + size[1]],
410
+ bottomRight: [origin[0] + size[0], origin[1] + size[1]]
411
+ };
412
+ return calculatePhysicalLayoutAux(element, size, origin, corners);
413
+ }
414
+ function calculatePhysicalLayoutAux(element, size, origin, corners) {
415
+ if (!element.direction) {
416
+ return calculatePhysicalLayoutLeaf(element, size, origin, corners);
417
+ }
418
+ else {
419
+ return calculatePhysicalLayoutElements(element, size, origin, corners);
420
+ }
421
+ }
422
+ export function calculateOffsettedCorners(rawSize, corners, offsets) {
423
+ function realOffset(offset) {
424
+ return [offset[0] * rawSize[0], offset[1] * rawSize[1]];
425
+ }
426
+ const offsettedCorners = {
427
+ topLeft: add2D(corners.topLeft, realOffset(offsets.topLeft)),
428
+ topRight: add2D(corners.topRight, realOffset(offsets.topRight)),
429
+ bottomLeft: add2D(corners.bottomLeft, realOffset(offsets.bottomLeft)),
430
+ bottomRight: add2D(corners.bottomRight, realOffset(offsets.bottomRight)),
431
+ };
432
+ return offsettedCorners;
433
+ }
434
+ function calculatePhysicalLayoutElements(element, rawSize, rawOrigin, corners) {
435
+ const [origin, size] = paddedSquare(rawOrigin, rawSize, element.cornerOffsets);
436
+ const offsettedCorners = calculateOffsettedCorners(rawSize, corners, element.cornerOffsets);
437
+ const dir = element.direction;
438
+ const psize = element.localLength;
439
+ const ssize = element.localBreadth;
440
+ const xf = dir == 'h' ? size[0] / psize : size[0] / ssize;
441
+ const yf = dir == 'v' ? size[1] / psize : size[1] / ssize;
442
+ const inner_width = ssize * xf;
443
+ const inner_height = ssize * yf;
444
+ const children = [];
445
+ if (dir == 'h') {
446
+ let x = 0;
447
+ const y = 0;
448
+ const leftmostLine = line(offsettedCorners.topLeft, offsettedCorners.bottomLeft);
449
+ const rightmostLine = line(offsettedCorners.topRight, offsettedCorners.bottomRight);
450
+ const topLine = line(offsettedCorners.topLeft, offsettedCorners.topRight);
451
+ const bottomLine = line(offsettedCorners.bottomLeft, offsettedCorners.bottomRight);
452
+ for (let i = 0; i < element.children.length; i++) {
453
+ const child = element.children[i];
454
+ const childSize = [child.rawSize * xf, inner_height];
455
+ const childOrigin = [origin[0] + size[0] - x * xf - childSize[0], origin[1] + y * yf];
456
+ const rightCenter = [childOrigin[0] + childSize[0], childOrigin[1] + childSize[1] / 2];
457
+ const leftCenter = [childOrigin[0], childOrigin[1] + childSize[1] / 2];
458
+ const rightLine = i === 0 ? rightmostLine : line2(rightCenter, deg2rad(element.children[i - 1].divider.slant + 90));
459
+ const leftLine = i === element.children.length - 1 ? leftmostLine : line2(leftCenter, deg2rad(child.divider.slant + 90));
460
+ const childCorners = {
461
+ topLeft: lineIntersection(topLine, leftLine),
462
+ topRight: lineIntersection(topLine, rightLine),
463
+ bottomLeft: lineIntersection(bottomLine, leftLine),
464
+ bottomRight: lineIntersection(bottomLine, rightLine),
465
+ };
466
+ children.push(calculatePhysicalLayoutAux(child, childSize, childOrigin, childCorners));
467
+ x += child.rawSize + child.divider.spacing;
468
+ }
469
+ }
470
+ else {
471
+ const x = 0;
472
+ let y = 0;
473
+ const topmostLine = line(offsettedCorners.topLeft, offsettedCorners.topRight);
474
+ const bottommostLine = line(offsettedCorners.bottomLeft, offsettedCorners.bottomRight);
475
+ const leftLine = line(offsettedCorners.topLeft, offsettedCorners.bottomLeft);
476
+ const rightLine = line(offsettedCorners.topRight, offsettedCorners.bottomRight);
477
+ for (let i = 0; i < element.children.length; i++) {
478
+ const child = element.children[i];
479
+ const childSize = [inner_width, child.rawSize * yf];
480
+ const childOrigin = [origin[0] + x * xf, origin[1] + y * yf];
481
+ const topCenter = [childOrigin[0] + childSize[0] / 2, childOrigin[1]];
482
+ const bottomCenter = [childOrigin[0] + childSize[0] / 2, childOrigin[1] + childSize[1]];
483
+ const topLine = i === 0 ? topmostLine : line2(topCenter, deg2rad(-element.children[i - 1].divider.slant));
484
+ const bottomLine = i === element.children.length - 1 ? bottommostLine : line2(bottomCenter, deg2rad(-child.divider.slant));
485
+ const childCorners = {
486
+ topLeft: lineIntersection(topLine, leftLine),
487
+ topRight: lineIntersection(topLine, rightLine),
488
+ bottomLeft: lineIntersection(bottomLine, leftLine),
489
+ bottomRight: lineIntersection(bottomLine, rightLine),
490
+ };
491
+ children.push(calculatePhysicalLayoutAux(child, childSize, childOrigin, childCorners));
492
+ y += child.rawSize + child.divider.spacing;
493
+ }
494
+ }
495
+ return { size, origin, rawSize, rawOrigin, children, element, dir, corners, formalCorners: corners };
496
+ }
497
+ function calculatePhysicalLayoutLeaf(element, rawSize, rawOrigin, formalCorners) {
498
+ const [origin, size] = paddedSquare(rawOrigin, rawSize, element.cornerOffsets);
499
+ const offsettedCorners = calculateOffsettedCorners(rawSize, formalCorners, element.cornerOffsets);
500
+ const topLine = line(offsettedCorners.topLeft, offsettedCorners.topRight);
501
+ const bottomLine = line(offsettedCorners.bottomLeft, offsettedCorners.bottomRight);
502
+ const leftLine = line(offsettedCorners.topLeft, offsettedCorners.bottomLeft);
503
+ const rightLine = line(offsettedCorners.topRight, offsettedCorners.bottomRight);
504
+ // 長さが0のときは交点を作れない
505
+ const corners = {
506
+ topLeft: lineIntersection(topLine, leftLine) || formalCorners.topLeft,
507
+ topRight: lineIntersection(topLine, rightLine) || formalCorners.topRight,
508
+ bottomLeft: lineIntersection(bottomLine, leftLine) || formalCorners.bottomLeft,
509
+ bottomRight: lineIntersection(bottomLine, rightLine) || formalCorners.bottomRight,
510
+ };
511
+ return { size, origin, rawSize, rawOrigin, element, corners, formalCorners, dir: null };
512
+ }
513
+ export function findLayoutAt(layout, point, margin, current = null) {
514
+ const layoutlets = collectLayoutlets(layout);
515
+ layoutlets.sort((a, b) => a.element.z - b.element.z);
516
+ layoutlets.reverse();
517
+ let result = null;
518
+ let distance = Infinity;
519
+ // currentがあってcurrentにヒットする場合、それより奥のものを返す
520
+ let selectableFlag = true;
521
+ if (current) {
522
+ const d = pointToQuadrilateralDistance(point, current.corners, false);
523
+ if (d <= margin) {
524
+ selectableFlag = false;
525
+ }
526
+ }
527
+ let index = 0;
528
+ for (let layoutlet of layoutlets) {
529
+ index++;
530
+ if (!selectableFlag) {
531
+ if (layoutlet.element === current?.element) {
532
+ selectableFlag = true;
533
+ }
534
+ continue;
535
+ }
536
+ const d = pointToQuadrilateralDistance(point, layoutlet.corners, false);
537
+ if (d <= margin && d < distance) {
538
+ distance = d;
539
+ result = layoutlet;
540
+ }
541
+ }
542
+ return result;
543
+ }
544
+ export function listLayoutsAt(layout, point, margin) {
545
+ const layoutlets = collectLayoutlets(layout);
546
+ layoutlets.sort((a, b) => a.element.z - b.element.z);
547
+ layoutlets.reverse();
548
+ const results = [];
549
+ for (let layoutlet of layoutlets) {
550
+ const d = pointToQuadrilateralDistance(point, layoutlet.corners, false);
551
+ if (d <= margin) {
552
+ results.push(layoutlet);
553
+ }
554
+ }
555
+ return results;
556
+ }
557
+ function collectLayoutlets(layout) {
558
+ const layouts = [];
559
+ ;
560
+ if (layout.children) {
561
+ for (let i = 0; i < layout.children.length; i++) {
562
+ const childLayouts = collectLayoutlets(layout.children[i]);
563
+ layouts.push(...childLayouts);
564
+ }
565
+ }
566
+ else {
567
+ layouts.push(layout);
568
+ }
569
+ return layouts;
570
+ }
571
+ export function findLayoutOf(layout, element) {
572
+ if (layout.element === element) {
573
+ return layout;
574
+ }
575
+ if (layout.children) {
576
+ for (let i = 0; i < layout.children.length; i++) {
577
+ const found = findLayoutOf(layout.children[i], element);
578
+ if (found) {
579
+ return found;
580
+ }
581
+ }
582
+ }
583
+ return null;
584
+ }
585
+ export function findBorderAt(layout, point, margin) {
586
+ if (layout.children) {
587
+ for (let i = 1; i < layout.children.length; i++) {
588
+ const corners = makeBorderCorners(layout, i, 0);
589
+ const q = pointToQuadrilateralDistance(point, corners, true);
590
+ if (q <= margin) {
591
+ const formalCorners = makeBorderFormalCorners(layout, i);
592
+ return { layout, index: i, corners, formalCorners };
593
+ }
594
+ }
595
+ for (let i = 0; i < layout.children.length; i++) {
596
+ const found = findBorderAt(layout.children[i], point, margin);
597
+ if (found) {
598
+ return found;
599
+ }
600
+ }
601
+ }
602
+ return null;
603
+ }
604
+ export function findPaddingAt(layout, position, innerWidth, outerWidth) {
605
+ const [x, y] = position;
606
+ if (layout.children) {
607
+ for (let i = 0; i < layout.children.length; i++) {
608
+ const found = findPaddingAt(layout.children[i], position, innerWidth, outerWidth);
609
+ if (found) {
610
+ return found;
611
+ }
612
+ }
613
+ return null;
614
+ }
615
+ else {
616
+ return findPaddingOn(layout, position, innerWidth, outerWidth);
617
+ }
618
+ }
619
+ export function findPaddingOn(layout, position, innerWidth, outerWidth) {
620
+ if (layout.element.visibility === 0) {
621
+ return null;
622
+ }
623
+ const [x, y] = position;
624
+ for (let handle of rectHandles) {
625
+ const paddingTrapezoid = makePaddingTrapezoid(layout, handle, innerWidth, outerWidth);
626
+ if (isPointInTrapezoid([x, y], paddingTrapezoid)) {
627
+ return { layout, handle, corners: paddingTrapezoid };
628
+ }
629
+ }
630
+ return null;
631
+ }
632
+ export function findPaddingOf(layout, handle, innerWidth, outerWidth) {
633
+ const corners = makePaddingTrapezoid(layout, handle, innerWidth, outerWidth);
634
+ return { layout, handle, corners };
635
+ }
636
+ export function makePaddingTrapezoid(layout, handle, innerWidth, outerWidth) {
637
+ switch (handle) {
638
+ case 'topLeft':
639
+ {
640
+ const [x, y] = layout.corners.topLeft;
641
+ return {
642
+ topLeft: [x - outerWidth, y - outerWidth],
643
+ topRight: [x + innerWidth, y - outerWidth],
644
+ bottomRight: [x + innerWidth, y + innerWidth],
645
+ bottomLeft: [x - outerWidth, y + innerWidth],
646
+ };
647
+ }
648
+ case 'topRight':
649
+ {
650
+ const [x, y] = layout.corners.topRight;
651
+ return {
652
+ topLeft: [x - innerWidth, y - outerWidth],
653
+ topRight: [x + outerWidth, y - outerWidth],
654
+ bottomRight: [x + outerWidth, y + innerWidth],
655
+ bottomLeft: [x - innerWidth, y + innerWidth],
656
+ };
657
+ }
658
+ case 'bottomLeft':
659
+ {
660
+ const [x, y] = layout.corners.bottomLeft;
661
+ return {
662
+ topLeft: [x - outerWidth, y - innerWidth],
663
+ topRight: [x + innerWidth, y - innerWidth],
664
+ bottomRight: [x + innerWidth, y + outerWidth],
665
+ bottomLeft: [x - outerWidth, y + outerWidth],
666
+ };
667
+ }
668
+ case 'bottomRight':
669
+ {
670
+ const [x, y] = layout.corners.bottomRight;
671
+ return {
672
+ topLeft: [x - innerWidth, y - innerWidth],
673
+ topRight: [x + outerWidth, y - innerWidth],
674
+ bottomRight: [x + outerWidth, y + outerWidth],
675
+ bottomLeft: [x - innerWidth, y + outerWidth],
676
+ };
677
+ }
678
+ case 'top':
679
+ return trapezoidAroundSegment(layout.corners.topLeft, layout.corners.topRight, outerWidth, innerWidth);
680
+ case 'bottom':
681
+ return trapezoidAroundSegment(layout.corners.bottomRight, layout.corners.bottomLeft, outerWidth, innerWidth);
682
+ case 'left':
683
+ return trapezoidAroundSegment(layout.corners.bottomLeft, layout.corners.topLeft, outerWidth, innerWidth);
684
+ case 'right':
685
+ return trapezoidAroundSegment(layout.corners.topRight, layout.corners.bottomRight, outerWidth, innerWidth);
686
+ }
687
+ }
688
+ function trapezoidAroundSegment(p0, p1, leftWidth, rightWidth) {
689
+ const [x0, y0] = p0;
690
+ const [x1, y1] = p1;
691
+ const dx = x1 - x0;
692
+ const dy = y1 - y0;
693
+ const d = Math.sqrt(dx * dx + dy * dy);
694
+ const nx = dx / d;
695
+ const ny = dy / d;
696
+ const wx = ny * leftWidth;
697
+ const wy = -nx * leftWidth;
698
+ const ex = ny * -rightWidth;
699
+ const ey = -nx * -rightWidth;
700
+ return {
701
+ topLeft: [x0 + wx, y0 + wy],
702
+ topRight: [x1 + wx, y1 + wy],
703
+ bottomRight: [x1 + ex, y1 + ey],
704
+ bottomLeft: [x0 + ex, y0 + ey],
705
+ };
706
+ }
707
+ export function makeBorderFormalCorners(layout, index) {
708
+ if (layout.dir == 'h') {
709
+ return makeHorizontalBorderFormalCorners(layout, index);
710
+ }
711
+ else {
712
+ return makeVerticalBorderFormalCorners(layout, index);
713
+ }
714
+ }
715
+ function makeHorizontalBorderFormalCorners(layout, index) {
716
+ const prev = layout.children[index - 1];
717
+ const curr = layout.children[index];
718
+ const corners = {
719
+ topLeft: [...curr.formalCorners.topRight],
720
+ topRight: [...prev.formalCorners.topLeft],
721
+ bottomLeft: [...curr.formalCorners.bottomRight],
722
+ bottomRight: [...prev.formalCorners.bottomLeft],
723
+ };
724
+ return corners;
725
+ }
726
+ function makeVerticalBorderFormalCorners(layout, index) {
727
+ const prev = layout.children[index - 1];
728
+ const curr = layout.children[index];
729
+ const corners = {
730
+ topLeft: [...prev.formalCorners.bottomLeft],
731
+ topRight: [...prev.formalCorners.bottomRight],
732
+ bottomLeft: [...curr.formalCorners.topLeft],
733
+ bottomRight: [...curr.formalCorners.topRight],
734
+ };
735
+ return corners;
736
+ }
737
+ const BORDER_WIDTH = 10;
738
+ export function makeBorderCorners(layout, index, margin) {
739
+ if (layout.dir == 'h') {
740
+ return makeHorizontalBorderCorners(layout, index, margin);
741
+ }
742
+ else {
743
+ return makeVerticalBorderCorners(layout, index, margin);
744
+ }
745
+ }
746
+ function makeHorizontalBorderCorners(layout, index, margin) {
747
+ const prev = layout.children[index - 1];
748
+ const curr = layout.children[index];
749
+ const corners = {
750
+ topLeft: [...curr.corners.topRight],
751
+ topRight: [...prev.corners.topLeft],
752
+ bottomLeft: [...curr.corners.bottomRight],
753
+ bottomRight: [...prev.corners.bottomLeft],
754
+ };
755
+ return extendTrapezoid(corners, margin, 0);
756
+ }
757
+ function makeVerticalBorderCorners(layout, index, margin) {
758
+ const prev = layout.children[index - 1];
759
+ const curr = layout.children[index];
760
+ const corners = {
761
+ topLeft: [...prev.corners.bottomLeft],
762
+ topRight: [...prev.corners.bottomRight],
763
+ bottomLeft: [...curr.corners.topLeft],
764
+ bottomRight: [...curr.corners.topRight],
765
+ };
766
+ return extendTrapezoid(corners, 0, margin);
767
+ }
768
+ export function collectImages(frameTree) {
769
+ const images = [];
770
+ if (!frameTree.children || frameTree.children.length === 0) {
771
+ if (0 < frameTree.visibility) {
772
+ images.push(frameTree.filmStack);
773
+ }
774
+ }
775
+ else {
776
+ for (let i = 0; i < frameTree.children.length; i++) {
777
+ const childImages = collectImages(frameTree.children[i]);
778
+ images.push(...childImages);
779
+ }
780
+ }
781
+ return images;
782
+ }
783
+ export function dealImages(frameTree, filmStacks, insertElement, spliceElement) {
784
+ if (!frameTree.children || frameTree.children.length === 0) {
785
+ if (frameTree.visibility === 0) {
786
+ return;
787
+ }
788
+ if (frameTree === spliceElement) {
789
+ filmStacks.shift();
790
+ }
791
+ if (frameTree === insertElement || filmStacks.length === 0) {
792
+ frameTree.filmStack = new FilmStack();
793
+ return;
794
+ }
795
+ const filmStack = filmStacks.shift();
796
+ frameTree.filmStack = filmStack;
797
+ }
798
+ else {
799
+ for (let i = 0; i < frameTree.children.length; i++) {
800
+ dealImages(frameTree.children[i], filmStacks, insertElement, spliceElement);
801
+ }
802
+ }
803
+ }
804
+ export function collectLeaves(frameTree) {
805
+ const leaves = [];
806
+ if (!frameTree.children || frameTree.children.length === 0) {
807
+ if (0 < frameTree.visibility && !frameTree.pseudo) {
808
+ leaves.push(frameTree);
809
+ }
810
+ }
811
+ else {
812
+ for (let i = 0; i < frameTree.children.length; i++) {
813
+ const childLeaves = collectLeaves(frameTree.children[i]);
814
+ leaves.push(...childLeaves);
815
+ }
816
+ }
817
+ return leaves;
818
+ }
819
+ export function constraintTree(paperSize, layout) {
820
+ const newLayout = calculatePhysicalLayout(layout.element, layout.size, layout.origin);
821
+ constraintRecursive(paperSize, newLayout);
822
+ }
823
+ export function constraintRecursive(paperSize, layout) {
824
+ if (layout.children) {
825
+ for (const child of layout.children) {
826
+ constraintRecursive(paperSize, child);
827
+ }
828
+ }
829
+ else if (layout.element) {
830
+ constraintLeaf(paperSize, layout);
831
+ }
832
+ }
833
+ export function constraintLeaf(paperSize, layout) {
834
+ if (!layout.corners) {
835
+ return;
836
+ }
837
+ if (layout.element.filmStack.films.length == 0) {
838
+ return;
839
+ }
840
+ const films = layout.element.filmStack.getOperationTargetFilms();
841
+ constraintFilms(paperSize, layout, films);
842
+ }
843
+ export function constraintFilms(paperSize, layout, films) {
844
+ if (!layout.corners) {
845
+ return;
846
+ }
847
+ const constraintRect = trapezoidBoundingRect(layout.corners);
848
+ const constraintCenter = getRectCenter(constraintRect);
849
+ const mergedRect = calculateMinimumBoundingRect(paperSize, films);
850
+ const { scale: targetScale, translation: targetTranslation } = computeConstraintedRect(translateRect(mergedRect, constraintCenter), constraintRect);
851
+ const rootMatrix = new DOMMatrix();
852
+ rootMatrix.scaleSelf(targetScale, targetScale);
853
+ rootMatrix.translateSelf(...targetTranslation);
854
+ films.forEach(film => {
855
+ const m = rootMatrix.multiply(film.makeMatrix(paperSize));
856
+ const scale = Math.sqrt(m.a * m.a + m.b * m.b);
857
+ film.setShiftedScale(paperSize, scale);
858
+ film.setShiftedTranslation(paperSize, [m.e, m.f]);
859
+ });
860
+ }
861
+ //# sourceMappingURL=frameTree.js.map