@jax-data-science/sci-image-visualizer 0.9.0 → 0.10.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 (131) hide show
  1. package/esm2022/index.mjs +7 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  6. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/viz-config.mjs +1 -1
  8. package/esm2022/lib/geometry/loft.mjs +128 -0
  9. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  10. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  11. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  12. package/esm2022/lib/geometry/section.mjs +215 -0
  13. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
  14. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
  15. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  16. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
  17. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
  19. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
  20. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
  21. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  22. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
  23. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  24. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
  25. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
  27. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
  28. package/esm2022/lib/models/class-preset.mjs +1 -1
  29. package/esm2022/lib/models/polygon-factory.mjs +17 -1
  30. package/esm2022/lib/models/region-geojson.mjs +44 -6
  31. package/esm2022/lib/models/region.mjs +1 -1
  32. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  33. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  34. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
  35. package/esm2022/lib/region-editor/region-editor.component.mjs +527 -42
  36. package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
  37. package/esm2022/lib/region-editor/region-persistence.service.mjs +36 -10
  38. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
  39. package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
  40. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  41. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  42. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  43. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  44. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  45. package/esm2022/lib/region-source/region-source.mjs +67 -0
  46. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  47. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  48. package/esm2022/lib/routing-visualizer.service.mjs +418 -22
  49. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  50. package/esm2022/lib/store/class-color.util.mjs +10 -5
  51. package/esm2022/lib/store/class-signatures.mjs +63 -0
  52. package/esm2022/lib/store/region-scope-cache.mjs +5 -1
  53. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  54. package/esm2022/lib/store/region-store.service.mjs +724 -12
  55. package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
  56. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
  57. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
  58. package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
  59. package/esm2022/lib/visualizer/region-load.mjs +67 -4
  60. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  61. package/esm2022/lib/visualizer.component.mjs +128 -6
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs} +7239 -1153
  63. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  64. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs} +4 -4
  65. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map} +1 -1
  66. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  67. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  68. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
  69. package/fesm2022/region-source.worker.js +1067 -0
  70. package/index.d.ts +6 -0
  71. package/lib/contracts/image.contract.d.ts +4 -0
  72. package/lib/contracts/region-editor-api.contract.d.ts +84 -0
  73. package/lib/contracts/region-store.contract.d.ts +22 -0
  74. package/lib/contracts/section-view.contract.d.ts +44 -0
  75. package/lib/contracts/visualizer.contract.d.ts +10 -0
  76. package/lib/contracts/viz-config.d.ts +8 -0
  77. package/lib/geometry/loft.d.ts +22 -0
  78. package/lib/geometry/polylabel.d.ts +23 -0
  79. package/lib/geometry/reconstruct.d.ts +54 -0
  80. package/lib/geometry/reslice-image.d.ts +33 -0
  81. package/lib/geometry/section.d.ts +52 -0
  82. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
  83. package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
  84. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  85. package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
  86. package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
  87. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
  88. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
  89. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  90. package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
  91. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  92. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
  93. package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
  94. package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
  95. package/lib/models/class-preset.d.ts +7 -0
  96. package/lib/models/polygon-factory.d.ts +5 -0
  97. package/lib/models/region-geojson.d.ts +40 -0
  98. package/lib/models/region.d.ts +19 -0
  99. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  100. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  101. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
  102. package/lib/region-editor/region-editor.component.d.ts +133 -17
  103. package/lib/region-editor/region-metrics.d.ts +8 -0
  104. package/lib/region-editor/region-persistence.service.d.ts +12 -4
  105. package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
  106. package/lib/region-overlay/region-geometry.d.ts +4 -3
  107. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  108. package/lib/region-overlay/region-style.d.ts +52 -0
  109. package/lib/region-source/http-region-source.d.ts +45 -0
  110. package/lib/region-source/region-source-ops.d.ts +89 -0
  111. package/lib/region-source/region-source-worker.d.ts +7 -0
  112. package/lib/region-source/region-source.d.ts +82 -0
  113. package/lib/region-source/region-tiles.d.ts +289 -0
  114. package/lib/region-source/worker-region-source.d.ts +65 -0
  115. package/lib/routing-visualizer.service.d.ts +138 -1
  116. package/lib/section-pane/section-pane.component.d.ts +47 -0
  117. package/lib/store/class-color.util.d.ts +6 -3
  118. package/lib/store/class-signatures.d.ts +11 -0
  119. package/lib/store/region-scope-cache.d.ts +2 -0
  120. package/lib/store/region-source-scope.d.ts +68 -0
  121. package/lib/store/region-store.service.d.ts +206 -2
  122. package/lib/store/visualizer-store.service.d.ts +10 -0
  123. package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
  124. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
  125. package/lib/toolbar/toolbar.component.d.ts +9 -2
  126. package/lib/visualizer/region-load.d.ts +23 -4
  127. package/lib/visualizer/volume-sections.d.ts +64 -0
  128. package/lib/visualizer.component.d.ts +31 -0
  129. package/package.json +2 -2
  130. package/src/lib/assets/slice.svg +23 -0
  131. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
@@ -0,0 +1,378 @@
1
+ import { isAbortError } from '../region-source/region-source';
2
+ import { featureAt, featuresInRect, regionLevelFor, regionTileId, regionTilesInRect, } from '../region-source/region-tiles';
3
+ import { IDENTITY_AFFINE, ScreenLayer, applyAffine, svgEl } from './svg-region-renderer';
4
+ import { isFilled, placeInsideLabel, shapePaint } from './region-style';
5
+ /** Wait this long after the last camera change before planning tiles (ms). */
6
+ export const SOURCE_REPLAN_MS = 90;
7
+ /** The view is padded by this fraction on each side, so a short pan finds its tiles loaded. */
8
+ export const SOURCE_VIEW_MARGIN = 0.25;
9
+ /** At most this many tiles in view. */
10
+ export const SOURCE_MAX_TILES = 256;
11
+ /** A rubber band takes at most this many source features into the working set. */
12
+ export const SOURCE_MARQUEE_LIMIT = 2000;
13
+ /** Loaded tiles kept by the layer for drawing (the source caches more). */
14
+ const LAYER_TILE_LIMIT = 512;
15
+ /** Stroke width of a source outline, screen px (an unselected region's). */
16
+ const SOURCE_STROKE_PX = 2;
17
+ export class RegionSourceLayer {
18
+ constructor(svg, view$, size = () => svgSize(svg)) {
19
+ this.svg = svg;
20
+ this.size = size;
21
+ this.group = svgEl('g');
22
+ this.camera = IDENTITY_AFFINE;
23
+ /** Class labels inside the features, in screen space over the outlines. */
24
+ this.labelLayer = new ScreenLayer(svgEl('g'), (x, y) => applyAffine(this.camera, x, y));
25
+ /** Class name → depth in the source's class hierarchy (parents draw under their children). */
26
+ this.depthOf = new Map();
27
+ /** Class name → its parent class in the source's class hierarchy. */
28
+ this.parentOf = new Map();
29
+ this.view = null;
30
+ this.visible = true;
31
+ /** Loaded tiles of the current source and plane, by id, least recently used first. */
32
+ this.tiles = new Map();
33
+ /** The tiles the view wants now. */
34
+ this.wanted = [];
35
+ /** The features drawn, by id (each at the finest level loaded). */
36
+ this.drawn = new Map();
37
+ this.loading = null;
38
+ this.replanTimer = null;
39
+ this.drawFrame = null;
40
+ this.group.setAttribute('data-layer', 'region-source');
41
+ this.group.setAttribute('pointer-events', 'none');
42
+ this.labelLayer.group.setAttribute('data-layer', 'region-source-labels');
43
+ this.sub = view$.subscribe((view) => this.setView(view));
44
+ }
45
+ /** Follow the camera: rewrite the transform now, re-plan the tiles once it settles. */
46
+ setCamera(affine) {
47
+ if (!affine.every(Number.isFinite))
48
+ return;
49
+ if (affine.every((v, i) => v === this.camera[i]))
50
+ return;
51
+ this.camera = affine;
52
+ this.applyCamera();
53
+ this.labelLayer.reproject();
54
+ if (!this.view)
55
+ return;
56
+ if (this.replanTimer)
57
+ clearTimeout(this.replanTimer);
58
+ this.replanTimer = setTimeout(() => {
59
+ this.replanTimer = null;
60
+ this.replan();
61
+ }, SOURCE_REPLAN_MS);
62
+ }
63
+ /** Show or hide the source with the regions. */
64
+ setVisible(visible) {
65
+ if (visible === this.visible)
66
+ return;
67
+ this.visible = visible;
68
+ this.attach();
69
+ }
70
+ /**
71
+ * The source feature under world point (x, y) — inside an area, or within `tolerancePx`
72
+ * screen pixels of a polyline — from the features drawn; the innermost of nested ones.
73
+ */
74
+ featureAt(x, y, tolerancePx = 4) {
75
+ if (!this.view || !this.visible)
76
+ return null;
77
+ return featureAt(this.drawn.values(), x, y, tolerancePx / this.scale());
78
+ }
79
+ /** The drawn source features whose box meets the world box (the rubber band's rule). */
80
+ featuresInRect(x0, y0, x1, y1) {
81
+ if (!this.view || !this.visible)
82
+ return [];
83
+ return featuresInRect(this.drawn.values(), [x0, y0, x1, y1]);
84
+ }
85
+ destroy() {
86
+ this.sub.unsubscribe();
87
+ this.loading?.abort();
88
+ if (this.replanTimer)
89
+ clearTimeout(this.replanTimer);
90
+ if (this.drawFrame !== null)
91
+ cancelFrame(this.drawFrame);
92
+ this.group.parentNode?.removeChild(this.group);
93
+ this.labelLayer.group.parentNode?.removeChild(this.labelLayer.group);
94
+ }
95
+ setView(view) {
96
+ const prev = this.view;
97
+ this.view = view;
98
+ if (!view || prev?.source !== view.source || prev.plane !== view.plane) {
99
+ this.tiles.clear();
100
+ this.loading?.abort();
101
+ this.loading = null;
102
+ }
103
+ if (view && prev?.source !== view.source) {
104
+ const hierarchy = view.source.info.hierarchy ?? [];
105
+ this.depthOf = hierarchyDepths(hierarchy);
106
+ this.parentOf = new Map(hierarchy.filter((n) => n.parent).map((n) => [n.name, n.parent]));
107
+ }
108
+ this.attach();
109
+ if (view)
110
+ this.replan();
111
+ else
112
+ this.draw();
113
+ }
114
+ /** The layer is the svg's first child (under the regions) while it shows a source. */
115
+ attach() {
116
+ const show = !!this.view && this.visible;
117
+ const labels = this.labelLayer.group;
118
+ if (!show) {
119
+ this.group.parentNode?.removeChild(this.group);
120
+ labels.parentNode?.removeChild(labels);
121
+ return;
122
+ }
123
+ if (this.svg.firstChild !== this.group)
124
+ this.svg.insertBefore(this.group, this.svg.firstChild);
125
+ if (this.group.nextSibling !== labels)
126
+ this.svg.insertBefore(labels, this.group.nextSibling);
127
+ }
128
+ applyCamera() {
129
+ this.group.setAttribute('transform', `matrix(${this.camera.join(' ')})`);
130
+ }
131
+ /** Screen px per world unit. */
132
+ scale() {
133
+ const [a, b, c, d] = this.camera;
134
+ return Math.sqrt(Math.abs(a * d - b * c)) || 1;
135
+ }
136
+ /** The world box in view, padded by the margin; null when the svg has no size yet. */
137
+ viewRect() {
138
+ const { width, height } = this.size();
139
+ if (!(width > 0) || !(height > 0))
140
+ return null;
141
+ const [a, b, c, d, e, f] = this.camera;
142
+ const det = a * d - b * c;
143
+ if (!det)
144
+ return null;
145
+ const toWorld = (sx, sy) => {
146
+ const x = sx - e, y = sy - f;
147
+ return [(d * x - c * y) / det, (a * y - b * x) / det];
148
+ };
149
+ const mx = width * SOURCE_VIEW_MARGIN, my = height * SOURCE_VIEW_MARGIN;
150
+ const corners = [
151
+ toWorld(-mx, -my),
152
+ toWorld(width + mx, -my),
153
+ toWorld(-mx, height + my),
154
+ toWorld(width + mx, height + my),
155
+ ];
156
+ const xs = corners.map((p) => p[0]), ys = corners.map((p) => p[1]);
157
+ return [Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)];
158
+ }
159
+ /** Work out the tiles the view needs, draw what is loaded, and load the rest. */
160
+ replan() {
161
+ const view = this.view;
162
+ if (!view)
163
+ return;
164
+ const rect = this.viewRect();
165
+ if (!rect) {
166
+ this.wanted = [];
167
+ this.draw();
168
+ return;
169
+ }
170
+ const info = view.source.info;
171
+ const level = regionLevelFor(this.scale(), info.levels);
172
+ this.wanted = regionTilesInRect(rect, level, info.tileSize, info.bounds, SOURCE_MAX_TILES);
173
+ this.scheduleDraw();
174
+ const missing = this.wanted.filter((k) => !this.tiles.has(regionTileId(k)));
175
+ this.loading?.abort();
176
+ this.loading = null;
177
+ if (!missing.length)
178
+ return;
179
+ const loading = new AbortController();
180
+ this.loading = loading;
181
+ for (const key of missing) {
182
+ view.source.getTile(view.plane, key, loading.signal).then((tile) => {
183
+ if (this.view?.source !== view.source || this.view.plane !== view.plane)
184
+ return;
185
+ this.keep(tile);
186
+ this.scheduleDraw();
187
+ }, (err) => {
188
+ if (!isAbortError(err))
189
+ console.warn('[regions] region tile failed', err);
190
+ });
191
+ }
192
+ }
193
+ keep(tile) {
194
+ const id = regionTileId(tile);
195
+ this.tiles.delete(id);
196
+ this.tiles.set(id, tile);
197
+ while (this.tiles.size > LAYER_TILE_LIMIT)
198
+ this.tiles.delete(this.tiles.keys().next().value);
199
+ }
200
+ scheduleDraw() {
201
+ if (this.drawFrame !== null)
202
+ return;
203
+ this.drawFrame = requestFrame(() => {
204
+ this.drawFrame = null;
205
+ this.draw();
206
+ });
207
+ }
208
+ /**
209
+ * Rebuild the paths from the wanted tiles that are loaded, a missing tile's nearest loaded
210
+ * ancestor standing in for it; each feature once, at the finest level loaded.
211
+ */
212
+ draw() {
213
+ const view = this.view;
214
+ const drawn = new Map();
215
+ const level = new Map();
216
+ if (view) {
217
+ const used = new Set();
218
+ for (const key of this.wanted) {
219
+ const tile = this.loadedOrAncestor(key);
220
+ if (!tile || used.has(regionTileId(tile)))
221
+ continue;
222
+ used.add(regionTileId(tile));
223
+ for (const f of tile.features) {
224
+ if (view.taken.has(f.id) || view.isHidden?.(f.label))
225
+ continue;
226
+ const had = level.get(f.id);
227
+ if (had !== undefined && had <= tile.level)
228
+ continue;
229
+ drawn.set(f.id, f);
230
+ level.set(f.id, tile.level);
231
+ }
232
+ }
233
+ }
234
+ this.drawn = drawn;
235
+ const filled = !!view && isFilled(view.style);
236
+ const frag = document.createDocumentFragment();
237
+ for (const run of this.runs(drawn, filled)) {
238
+ const path = svgEl('path');
239
+ path.setAttribute('d', run.features.flatMap((f) => f.rings.map((r) => ringD(r, !f.open))).join(''));
240
+ path.setAttribute('fill-rule', 'evenodd');
241
+ path.setAttribute('stroke-linejoin', 'round');
242
+ path.setAttribute('vector-effect', 'non-scaling-stroke');
243
+ if (filled && view) {
244
+ const paint = shapePaint(run.color, false, view.style);
245
+ path.setAttribute('fill', paint.fill);
246
+ path.setAttribute('fill-opacity', `${paint.fillOpacity}`);
247
+ path.setAttribute('stroke', paint.stroke);
248
+ path.setAttribute('stroke-width', `${paint.strokeWidth}`);
249
+ }
250
+ else {
251
+ path.setAttribute('fill', 'none');
252
+ path.setAttribute('stroke', run.color);
253
+ path.setAttribute('stroke-width', `${SOURCE_STROKE_PX}`);
254
+ }
255
+ frag.appendChild(path);
256
+ }
257
+ while (this.group.firstChild)
258
+ this.group.removeChild(this.group.firstChild);
259
+ this.group.appendChild(frag);
260
+ this.applyCamera();
261
+ this.drawLabels(filled);
262
+ }
263
+ /**
264
+ * The drawn features as paths: one per colour when outlined; filled, in paint order — parents
265
+ * (by the class hierarchy) and then larger features first, so what lies inside paints over
266
+ * them — one path per run of a colour.
267
+ */
268
+ runs(drawn, filled) {
269
+ const view = this.view;
270
+ const colorOf = (f) => view?.colorOf(f) ?? '#00FFFF';
271
+ if (!filled) {
272
+ const byColor = new Map();
273
+ for (const f of drawn.values()) {
274
+ const color = colorOf(f);
275
+ const list = byColor.get(color);
276
+ if (list)
277
+ list.push(f);
278
+ else
279
+ byColor.set(color, [f]);
280
+ }
281
+ return Array.from(byColor, ([color, features]) => ({ color, features }));
282
+ }
283
+ const area = (f) => (f.bbox[2] - f.bbox[0]) * (f.bbox[3] - f.bbox[1]);
284
+ const depth = (f) => this.depthOf.get(f.label ?? '') ?? 0;
285
+ const order = Array.from(drawn.values()).sort((a, b) => depth(a) - depth(b) || area(b) - area(a));
286
+ const runs = [];
287
+ for (const f of order) {
288
+ const color = colorOf(f);
289
+ const last = runs[runs.length - 1];
290
+ if (last && last.color === color)
291
+ last.features.push(f);
292
+ else
293
+ runs.push({ color, features: [f] });
294
+ }
295
+ return runs;
296
+ }
297
+ /** Class labels inside the drawn features (each part where it fits), when labels are on. */
298
+ drawLabels(filled) {
299
+ this.labelLayer.clear();
300
+ const view = this.view;
301
+ if (!view?.labels)
302
+ return;
303
+ // Only the deepest classes drawn are labelled: a class whose subclasses are drawn too (an
304
+ // atlas's "Isocortex" under its areas) would only repeat over them.
305
+ const covered = new Set();
306
+ for (const f of this.drawn.values()) {
307
+ let p = f.label ? this.parentOf.get(f.label) : undefined;
308
+ while (p && !covered.has(p)) {
309
+ covered.add(p);
310
+ p = this.parentOf.get(p);
311
+ }
312
+ }
313
+ for (const f of this.drawn.values()) {
314
+ const at = f.labels;
315
+ if (!at || !f.label || covered.has(f.label))
316
+ continue;
317
+ const color = filled ? '#111' : view.colorOf(f);
318
+ for (let k = 0; k + 2 < at.length; k += 3) {
319
+ placeInsideLabel(this.labelLayer, f.label, { x: at[k], y: at[k + 1], room: at[k + 2] }, color);
320
+ }
321
+ }
322
+ }
323
+ /** The loaded tile for `key`, else its nearest loaded coarser ancestor. */
324
+ loadedOrAncestor(key) {
325
+ const levels = this.view?.source.info.levels ?? 0;
326
+ let { gx, gy } = key;
327
+ for (let level = key.level; level < levels; level++) {
328
+ const tile = this.tiles.get(regionTileId({ level, gx, gy }));
329
+ if (tile)
330
+ return tile;
331
+ gx = Math.floor(gx / 2);
332
+ gy = Math.floor(gy / 2);
333
+ }
334
+ return null;
335
+ }
336
+ }
337
+ /** Path data of one ring (`closed`) or polyline, in world units to 1/100. */
338
+ function ringD(ring, closed) {
339
+ const n = ring.length >> 1;
340
+ if (n < 2)
341
+ return '';
342
+ let d = `M${r2(ring[0])} ${r2(ring[1])}`;
343
+ for (let i = 1; i < n; i++)
344
+ d += `L${r2(ring[2 * i])} ${r2(ring[2 * i + 1])}`;
345
+ return closed ? `${d}Z` : d;
346
+ }
347
+ function r2(v) {
348
+ return Math.round(v * 100) / 100;
349
+ }
350
+ function svgSize(svg) {
351
+ const width = svg.clientWidth || svg.getBoundingClientRect().width;
352
+ const height = svg.clientHeight || svg.getBoundingClientRect().height;
353
+ return { width, height };
354
+ }
355
+ const requestFrame = (fn) => typeof requestAnimationFrame === 'function'
356
+ ? requestAnimationFrame(fn)
357
+ : setTimeout(fn, 16);
358
+ const cancelFrame = (id) => typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame(id) : clearTimeout(id);
359
+ /** Depth of each class in a class hierarchy (a root is 0); empty without one. */
360
+ function hierarchyDepths(hierarchy) {
361
+ const depths = new Map();
362
+ if (!hierarchy)
363
+ return depths;
364
+ const parent = new Map(hierarchy.map((n) => [n.name, n.parent ?? null]));
365
+ for (const n of hierarchy) {
366
+ let d = 0;
367
+ let p = parent.get(n.name);
368
+ const seen = new Set([n.name]);
369
+ while (p && !seen.has(p)) {
370
+ seen.add(p);
371
+ d++;
372
+ p = parent.get(p) ?? null;
373
+ }
374
+ depths.set(n.name, d);
375
+ }
376
+ return depths;
377
+ }
378
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXNvdXJjZS1sYXllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvcmVnaW9uLW92ZXJsYXkvcmVnaW9uLXNvdXJjZS1sYXllci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFpQkEsT0FBTyxFQUFvQixZQUFZLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNoRixPQUFPLEVBS0wsU0FBUyxFQUNULGNBQWMsRUFDZCxjQUFjLEVBQ2QsWUFBWSxFQUNaLGlCQUFpQixHQUNsQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLE9BQU8sRUFBVSxlQUFlLEVBQUUsV0FBVyxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNqRyxPQUFPLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXhFLDhFQUE4RTtBQUM5RSxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7QUFDbkMsK0ZBQStGO0FBQy9GLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQztBQUN2Qyx1Q0FBdUM7QUFDdkMsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBQ3BDLGtGQUFrRjtBQUNsRixNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUM7QUFDekMsMkVBQTJFO0FBQzNFLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBQzdCLDRFQUE0RTtBQUM1RSxNQUFNLGdCQUFnQixHQUFHLENBQUMsQ0FBQztBQUszQixNQUFNLE9BQU8saUJBQWlCO0lBc0I1QixZQUNtQixHQUFrQixFQUNuQyxLQUEwQyxFQUN6QixPQUFnQixHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDO1FBRmxDLFFBQUcsR0FBSCxHQUFHLENBQWU7UUFFbEIsU0FBSSxHQUFKLElBQUksQ0FBOEI7UUF4QnBD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Q0FBQyxDQUFDLENBQUM7UUFDdkMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNaLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO1FBQzVCLENBQUM7UUFDRCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERyYXdzIGEgcmVnaW9uIHNvdXJjZSAoc2VlIGByZWdpb24tc291cmNlYCkgdW5kZXIgdGhlIGVkaXRhYmxlIHJlZ2lvbnMsIGF0IHRoZSBsZXZlbCBvZiBkZXRhaWxcbiAqIHRoZSB6b29tIGNhbGxzIGZvciwgZnJvbSB0aGUgdGlsZXMgaW4gdmlldyBvbmx5IOKAlCB0aGUgd2F5IHRoZSBzcGF0aWFsIHZpZXdzIGRyYXcgY2VsbCBvdXRsaW5lcy5cbiAqIFNoYXJlZCBieSB0aGUgT3BlblNlYWRyYWdvbiBhbmQgbmFwYXJpIG92ZXJsYXlzOiBib3RoIGhhbmQgaXQgdGhlaXIgc3ZnIGFuZCB0aGVpciB3b3JsZCDihpIgc3ZnXG4gKiBjYW1lcmEgYWZmaW5lLCBhcyB0aGV5IGRvIHRoZWlyIHtAbGluayBTdmdSZWdpb25SZW5kZXJlcn0uXG4gKlxuICogT25lIGA8cGF0aD5gIHBlciBjb2xvdXIgKGV2ZXJ5IHJpbmcgb2YgZXZlcnkgZmVhdHVyZSBvZiB0aGF0IGNvbG91ciwgZXZlbi1vZGQpLCBpbiB3b3JsZFxuICogY29vcmRpbmF0ZXMgaW5zaWRlIG9uZSB0cmFuc2Zvcm1lZCBncm91cCwgc28gYSBjYW1lcmEgbW92ZSByZXdyaXRlcyBvbmUgYXR0cmlidXRlLiBUaGUgdGlsZXMgaW5cbiAqIHZpZXcgYXJlIHJlLXBsYW5uZWQgb25jZSB0aGUgY2FtZXJhIHNldHRsZXM7IHdoaWxlIGEgZmluZXIgdGlsZSBsb2FkcyBpdHMgY29hcnNlciBwYXJlbnQgaXNcbiAqIGRyYXduIGluc3RlYWQsIHNvIHpvb21pbmcgaW4gc2hhcnBlbnMgdGhlIG91dGxpbmVzIHJhdGhlciB0aGFuIGJsYW5raW5nIHRoZW0uIEZlYXR1cmVzIHRha2VuXG4gKiBpbnRvIHRoZSB3b3JraW5nIHNldCAoc2VsZWN0ZWQsIGVkaXRlZCkgb3IgZGVsZXRlZCBhcmUgbm90IGRyYXduOiB0aGUgcmVnaW9uIHJlbmRlcmVyIGRyYXdzIHRoZVxuICogdGFrZW4gb25lcyBhcyBvcmRpbmFyeSByZWdpb25zLlxuICpcbiAqIEl0IGFsc28gYW5zd2VycyB3aGF0IGlzIHVuZGVyIGEgcG9pbnQsIGZyb20gdGhlIGZlYXR1cmVzIGRyYXduLCBmb3IgdGhlIG92ZXJsYXlzJyBzZWxlY3Rpb24uXG4gKi9cbmltcG9ydCB0eXBlIHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFJlZ2lvblNvdXJjZVZpZXcsIGlzQWJvcnRFcnJvciB9IGZyb20gJy4uL3JlZ2lvbi1zb3VyY2UvcmVnaW9uLXNvdXJjZSc7XG5pbXBvcnQge1xuICBCYm94LFxuICBSZWdpb25UaWxlLFxuICBSZWdpb25UaWxlS2V5LFxuICBUaWxlRmVhdHVyZSxcbiAgZmVhdHVyZUF0LFxuICBmZWF0dXJlc0luUmVjdCxcbiAgcmVnaW9uTGV2ZWxGb3IsXG4gIHJlZ2lvblRpbGVJZCxcbiAgcmVnaW9uVGlsZXNJblJlY3QsXG59IGZyb20gJy4uL3JlZ2lvbi1zb3VyY2UvcmVnaW9uLXRpbGVzJztcbmltcG9ydCB7IEFmZmluZSwgSURFTlRJVFlfQUZGSU5FLCBTY3JlZW5MYXllciwgYXBwbHlBZmZpbmUsIHN2Z0VsIH0gZnJvbSAnLi9zdmctcmVnaW9uLXJlbmRlcmVyJztcbmltcG9ydCB7IGlzRmlsbGVkLCBwbGFjZUluc2lkZUxhYmVsLCBzaGFwZVBhaW50IH0gZnJvbSAnLi9yZWdpb24tc3R5bGUnO1xuXG4vKiogV2FpdCB0aGlzIGxvbmcgYWZ0ZXIgdGhlIGxhc3QgY2FtZXJhIGNoYW5nZSBiZWZvcmUgcGxhbm5pbmcgdGlsZXMgKG1zKS4gKi9cbmV4cG9ydCBjb25zdCBTT1VSQ0VfUkVQTEFOX01TID0gOTA7XG4vKiogVGhlIHZpZXcgaXMgcGFkZGVkIGJ5IHRoaXMgZnJhY3Rpb24gb24gZWFjaCBzaWRlLCBzbyBhIHNob3J0IHBhbiBmaW5kcyBpdHMgdGlsZXMgbG9hZGVkLiAqL1xuZXhwb3J0IGNvbnN0IFNPVVJDRV9WSUVXX01BUkdJTiA9IDAuMjU7XG4vKiogQXQgbW9zdCB0aGlzIG1hbnkgdGlsZXMgaW4gdmlldy4gKi9cbmV4cG9ydCBjb25zdCBTT1VSQ0VfTUFYX1RJTEVTID0gMjU2O1xuLyoqIEEgcnViYmVyIGJhbmQgdGFrZXMgYXQgbW9zdCB0aGlzIG1hbnkgc291cmNlIGZlYXR1cmVzIGludG8gdGhlIHdvcmtpbmcgc2V0LiAqL1xuZXhwb3J0IGNvbnN0IFNPVVJDRV9NQVJRVUVFX0xJTUlUID0gMjAwMDtcbi8qKiBMb2FkZWQgdGlsZXMga2VwdCBieSB0aGUgbGF5ZXIgZm9yIGRyYXdpbmcgKHRoZSBzb3VyY2UgY2FjaGVzIG1vcmUpLiAqL1xuY29uc3QgTEFZRVJfVElMRV9MSU1JVCA9IDUxMjtcbi8qKiBTdHJva2Ugd2lkdGggb2YgYSBzb3VyY2Ugb3V0bGluZSwgc2NyZWVuIHB4IChhbiB1bnNlbGVjdGVkIHJlZ2lvbidzKS4gKi9cbmNvbnN0IFNPVVJDRV9TVFJPS0VfUFggPSAyO1xuXG4vKiogVGhlIHN2ZyBzaXplIChsb2NhbCBweCksIGZvciB0aGUgcGFydCBvZiB0aGUgd29ybGQgaW4gdmlldy4gKi9cbmV4cG9ydCB0eXBlIFN2Z1NpemUgPSAoKSA9PiB7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH07XG5cbmV4cG9ydCBjbGFzcyBSZWdpb25Tb3VyY2VMYXllciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ3JvdXAgPSBzdmdFbCgnZycpO1xuICBwcml2YXRlIGNhbWVyYTogQWZmaW5lID0gSURFTlRJVFlfQUZGSU5FO1xuICAvKiogQ2xhc3MgbGFiZWxzIGluc2lkZSB0aGUgZmVhdHVyZXMsIGluIHNjcmVlbiBzcGFjZSBvdmVyIHRoZSBvdXRsaW5lcy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBsYWJlbExheWVyID0gbmV3IFNjcmVlbkxheWVyKHN2Z0VsKCdnJyksICh4LCB5KSA9PiBhcHBseUFmZmluZSh0aGlzLmNhbWVyYSwgeCwgeSkpO1xuICAvKiogQ2xhc3MgbmFtZSDihpIgZGVwdGggaW4gdGhlIHNvdXJjZSdzIGNsYXNzIGhpZXJhcmNoeSAocGFyZW50cyBkcmF3IHVuZGVyIHRoZWlyIGNoaWxkcmVuKS4gKi9cbiAgcHJpdmF0ZSBkZXB0aE9mID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgLyoqIENsYXNzIG5hbWUg4oaSIGl0cyBwYXJlbnQgY2xhc3MgaW4gdGhlIHNvdXJjZSdzIGNsYXNzIGhpZXJhcmNoeS4gKi9cbiAgcHJpdmF0ZSBwYXJlbnRPZiA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIHByaXZhdGUgdmlldzogUmVnaW9uU291cmNlVmlldyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHZpc2libGUgPSB0cnVlO1xuICBwcml2YXRlIHJlYWRvbmx5IHN1YjogU3Vic2NyaXB0aW9uO1xuICAvKiogTG9hZGVkIHRpbGVzIG9mIHRoZSBjdXJyZW50IHNvdXJjZSBhbmQgcGxhbmUsIGJ5IGlkLCBsZWFzdCByZWNlbnRseSB1c2VkIGZpcnN0LiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHRpbGVzID0gbmV3IE1hcDxzdHJpbmcsIFJlZ2lvblRpbGU+KCk7XG4gIC8qKiBUaGUgdGlsZXMgdGhlIHZpZXcgd2FudHMgbm93LiAqL1xuICBwcml2YXRlIHdhbnRlZDogUmVnaW9uVGlsZUtleVtdID0gW107XG4gIC8qKiBUaGUgZmVhdHVyZXMgZHJhd24sIGJ5IGlkIChlYWNoIGF0IHRoZSBmaW5lc3QgbGV2ZWwgbG9hZGVkKS4gKi9cbiAgcHJpdmF0ZSBkcmF3biA9IG5ldyBNYXA8c3RyaW5nLCBUaWxlRmVhdHVyZT4oKTtcbiAgcHJpdmF0ZSBsb2FkaW5nOiBBYm9ydENvbnRyb2xsZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZXBsYW5UaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkcmF3RnJhbWU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc3ZnOiBTVkdTVkdFbGVtZW50LFxuICAgIHZpZXckOiBPYnNlcnZhYmxlPFJlZ2lvblNvdXJjZVZpZXcgfCBudWxsPixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNpemU6IFN2Z1NpemUgPSAoKSA9PiBzdmdTaXplKHN2ZyksXG4gICkge1xuICAgIHRoaXMuZ3JvdXAuc2V0QXR0cmlidXRlKCdkYXRhLWxheWVyJywgJ3JlZ2lvbi1zb3VyY2UnKTtcbiAgICB0aGlzLmdyb3VwLnNldEF0dHJpYnV0ZSgncG9pbnRlci1ldmVudHMnLCAnbm9uZScpO1xuICAgIHRoaXMubGFiZWxMYXllci5ncm91cC5zZXRBdHRyaWJ1dGUoJ2RhdGEtbGF5ZXInLCAncmVnaW9uLXNvdXJjZS1sYWJlbHMnKTtcbiAgICB0aGlzLnN1YiA9IHZpZXckLnN1YnNjcmliZSgodmlldykgPT4gdGhpcy5zZXRWaWV3KHZpZXcpKTtcbiAgfVxuXG4gIC8qKiBGb2xsb3cgdGhlIGNhbWVyYTogcmV3cml0ZSB0aGUgdHJhbnNmb3JtIG5vdywgcmUtcGxhbiB0aGUgdGlsZXMgb25jZSBpdCBzZXR0bGVzLiAqL1xuICBzZXRDYW1lcmEoYWZmaW5lOiBBZmZpbmUpOiB2b2lkIHtcbiAgICBpZiAoIWFmZmluZS5ldmVyeShOdW1iZXIuaXNGaW5pdGUpKSByZXR1cm47XG4gICAgaWYgKGFmZmluZS5ldmVyeSgodiwgaSkgPT4gdiA9PT0gdGhpcy5jYW1lcmFbaV0pKSByZXR1cm47XG4gICAgdGhpcy5jYW1lcmEgPSBhZmZpbmU7XG4gICAgdGhpcy5hcHBseUNhbWVyYSgpO1xuICAgIHRoaXMubGFiZWxMYXllci5yZXByb2plY3QoKTtcbiAgICBpZiAoIXRoaXMudmlldykgcmV0dXJuO1xuICAgIGlmICh0aGlzLnJlcGxhblRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy5yZXBsYW5UaW1lcik7XG4gICAgdGhpcy5yZXBsYW5UaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5yZXBsYW5UaW1lciA9IG51bGw7XG4gICAgICB0aGlzLnJlcGxhbigpO1xuICAgIH0sIFNPVVJDRV9SRVBMQU5fTVMpO1xuICB9XG5cbiAgLyoqIFNob3cgb3IgaGlkZSB0aGUgc291cmNlIHdpdGggdGhlIHJlZ2lvbnMuICovXG4gIHNldFZpc2libGUodmlzaWJsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICh2aXNpYmxlID09PSB0aGlzLnZpc2libGUpIHJldHVybjtcbiAgICB0aGlzLnZpc2libGUgPSB2aXNpYmxlO1xuICAgIHRoaXMuYXR0YWNoKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHNvdXJjZSBmZWF0dXJlIHVuZGVyIHdvcmxkIHBvaW50ICh4LCB5KSDigJQgaW5zaWRlIGFuIGFyZWEsIG9yIHdpdGhpbiBgdG9sZXJhbmNlUHhgXG4gICAqIHNjcmVlbiBwaXhlbHMgb2YgYSBwb2x5bGluZSDigJQgZnJvbSB0aGUgZmVhdHVyZXMgZHJhd247IHRoZSBpbm5lcm1vc3Qgb2YgbmVzdGVkIG9uZXMuXG4gICAqL1xuICBmZWF0dXJlQXQoeDogbnVtYmVyLCB5OiBudW1iZXIsIHRvbGVyYW5jZVB4ID0gNCk6IFRpbGVGZWF0dXJlIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLnZpZXcgfHwgIXRoaXMudmlzaWJsZSkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIGZlYXR1cmVBdCh0aGlzLmRyYXduLnZhbHVlcygpLCB4LCB5LCB0b2xlcmFuY2VQeCAvIHRoaXMuc2NhbGUoKSk7XG4gIH1cblxuICAvKiogVGhlIGRyYXduIHNvdXJjZSBmZWF0dXJlcyB3aG9zZSBib3ggbWVldHMgdGhlIHdvcmxkIGJveCAodGhlIHJ1YmJlciBiYW5kJ3MgcnVsZSkuICovXG4gIGZlYXR1cmVzSW5SZWN0KHgwOiBudW1iZXIsIHkwOiBudW1iZXIsIHgxOiBudW1iZXIsIHkxOiBudW1iZXIpOiBUaWxlRmVhdHVyZVtdIHtcbiAgICBpZiAoIXRoaXMudmlldyB8fCAhdGhpcy52aXNpYmxlKSByZXR1cm4gW107XG4gICAgcmV0dXJuIGZlYXR1cmVzSW5SZWN0KHRoaXMuZHJhd24udmFsdWVzKCksIFt4MCwgeTAsIHgxLCB5MV0pO1xuICB9XG5cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMubG9hZGluZz8uYWJvcnQoKTtcbiAgICBpZiAodGhpcy5yZXBsYW5UaW1lcikgY2xlYXJUaW1lb3V0KHRoaXMucmVwbGFuVGltZXIpO1xuICAgIGlmICh0aGlzLmRyYXdGcmFtZSAhPT0gbnVsbCkgY2FuY2VsRnJhbWUodGhpcy5kcmF3RnJhbWUpO1xuICAgIHRoaXMuZ3JvdXAucGFyZW50Tm9kZT8ucmVtb3ZlQ2hpbGQodGhpcy5ncm91cCk7XG4gICAgdGhpcy5sYWJlbExheWVyLmdyb3VwLnBhcmVudE5vZGU/LnJlbW92ZUNoaWxkKHRoaXMubGFiZWxMYXllci5ncm91cCk7XG4gIH1cblxuICBwcml2YXRlIHNldFZpZXcodmlldzogUmVnaW9uU291cmNlVmlldyB8IG51bGwpOiB2b2lkIHtcbiAgICBjb25zdCBwcmV2ID0gdGhpcy52aWV3O1xuICAgIHRoaXMudmlldyA9IHZpZXc7XG4gICAgaWYgKCF2aWV3IHx8IHByZXY/LnNvdXJjZSAhPT0gdmlldy5zb3VyY2UgfHwgcHJldi5wbGFuZSAhPT0gdmlldy5wbGFuZSkge1xuICAgICAgdGhpcy50aWxlcy5jbGVhcigpO1xuICAgICAgdGhpcy5sb2FkaW5nPy5hYm9ydCgpO1xuICAgICAgdGhpcy5sb2FkaW5nID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKHZpZXcgJiYgcHJldj8uc291cmNlICE9PSB2aWV3LnNvdXJjZSkge1xuICAgICAgY29uc3QgaGllcmFyY2h5ID0gdmlldy5zb3VyY2UuaW5mby5oaWVyYXJjaHkgPz8gW107XG4gICAgICB0aGlzLmRlcHRoT2YgPSBoaWVyYXJjaHlEZXB0aHMoaGllcmFyY2h5KTtcbiAgICAgIHRoaXMucGFyZW50T2YgPSBuZXcgTWFwKGhpZXJhcmNoeS5maWx0ZXIoKG4pID0+IG4ucGFyZW50KS5tYXAoKG4pID0+IFtuLm5hbWUsIG4ucGFyZW50IGFzIHN0cmluZ10pKTtcbiAgICB9XG4gICAgdGhpcy5hdHRhY2goKTtcbiAgICBpZiAodmlldykgdGhpcy5yZXBsYW4oKTtcbiAgICBlbHNlIHRoaXMuZHJhdygpO1xuICB9XG5cbiAgLyoqIFRoZSBsYXllciBpcyB0aGUgc3ZnJ3MgZmlyc3QgY2hpbGQgKHVuZGVyIHRoZSByZWdpb25zKSB3aGlsZSBpdCBzaG93cyBhIHNvdXJjZS4gKi9cbiAgcHJpdmF0ZSBhdHRhY2goKTogdm9pZCB7XG4gICAgY29uc3Qgc2hvdyA9ICEhdGhpcy52aWV3ICYmIHRoaXMudmlzaWJsZTtcbiAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmxhYmVsTGF5ZXIuZ3JvdXA7XG4gICAgaWYgKCFzaG93KSB7XG4gICAgICB0aGlzLmdyb3VwLnBhcmVudE5vZGU/LnJlbW92ZUNoaWxkKHRoaXMuZ3JvdXApO1xuICAgICAgbGFiZWxzLnBhcmVudE5vZGU/LnJlbW92ZUNoaWxkKGxhYmVscyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLnN2Zy5maXJzdENoaWxkICE9PSB0aGlzLmdyb3VwKSB0aGlzLnN2Zy5pbnNlcnRCZWZvcmUodGhpcy5ncm91cCwgdGhpcy5zdmcuZmlyc3RDaGlsZCk7XG4gICAgaWYgKHRoaXMuZ3JvdXAubmV4dFNpYmxpbmcgIT09IGxhYmVscykgdGhpcy5zdmcuaW5zZXJ0QmVmb3JlKGxhYmVscywgdGhpcy5ncm91cC5uZXh0U2libGluZyk7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5Q2FtZXJhKCk6IHZvaWQge1xuICAgIHRoaXMuZ3JvdXAuc2V0QXR0cmlidXRlKCd0cmFuc2Zvcm0nLCBgbWF0cml4KCR7dGhpcy5jYW1lcmEuam9pbignICcpfSlgKTtcbiAgfVxuXG4gIC8qKiBTY3JlZW4gcHggcGVyIHdvcmxkIHVuaXQuICovXG4gIHByaXZhdGUgc2NhbGUoKTogbnVtYmVyIHtcbiAgICBjb25zdCBbYSwgYiwgYywgZF0gPSB0aGlzLmNhbWVyYTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KE1hdGguYWJzKGEgKiBkIC0gYiAqIGMpKSB8fCAxO1xuICB9XG5cbiAgLyoqIFRoZSB3b3JsZCBib3ggaW4gdmlldywgcGFkZGVkIGJ5IHRoZSBtYXJnaW47IG51bGwgd2hlbiB0aGUgc3ZnIGhhcyBubyBzaXplIHlldC4gKi9cbiAgcHJpdmF0ZSB2aWV3UmVjdCgpOiBCYm94IHwgbnVsbCB7XG4gICAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSB0aGlzLnNpemUoKTtcbiAgICBpZiAoISh3aWR0aCA+IDApIHx8ICEoaGVpZ2h0ID4gMCkpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IFthLCBiLCBjLCBkLCBlLCBmXSA9IHRoaXMuY2FtZXJhO1xuICAgIGNvbnN0IGRldCA9IGEgKiBkIC0gYiAqIGM7XG4gICAgaWYgKCFkZXQpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHRvV29ybGQgPSAoc3g6IG51bWJlciwgc3k6IG51bWJlcik6IFtudW1iZXIsIG51bWJlcl0gPT4ge1xuICAgICAgY29uc3QgeCA9IHN4IC0gZSxcbiAgICAgICAgeSA9IHN5IC0gZjtcbiAgICAgIHJldHVybiBbKGQgKiB4IC0gYyAqIHkpIC8gZGV0LCAoYSAqIHkgLSBiICogeCkgLyBkZXRdO1xuICAgIH07XG4gICAgY29uc3QgbXggPSB3aWR0aCAqIFNPVVJDRV9WSUVXX01BUkdJTixcbiAgICAgIG15ID0gaGVpZ2h0ICogU09VUkNFX1ZJRVdfTUFSR0lOO1xuICAgIGNvbnN0IGNvcm5lcnMgPSBbXG4gICAgICB0b1dvcmxkKC1teCwgLW15KSxcbiAgICAgIHRvV29ybGQod2lkdGggKyBteCwgLW15KSxcbiAgICAgIHRvV29ybGQoLW14LCBoZWlnaHQgKyBteSksXG4gICAgICB0b1dvcmxkKHdpZHRoICsgbXgsIGhlaWdodCArIG15KSxcbiAgICBdO1xuICAgIGNvbnN0IHhzID0gY29ybmVycy5tYXAoKHApID0+IHBbMF0pLFxuICAgICAgeXMgPSBjb3JuZXJzLm1hcCgocCkgPT4gcFsxXSk7XG4gICAgcmV0dXJuIFtNYXRoLm1pbiguLi54cyksIE1hdGgubWluKC4uLnlzKSwgTWF0aC5tYXgoLi4ueHMpLCBNYXRoLm1heCguLi55cyldO1xuICB9XG5cbiAgLyoqIFdvcmsgb3V0IHRoZSB0aWxlcyB0aGUgdmlldyBuZWVkcywgZHJhdyB3aGF0IGlzIGxvYWRlZCwgYW5kIGxvYWQgdGhlIHJlc3QuICovXG4gIHByaXZhdGUgcmVwbGFuKCk6IHZvaWQge1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXc7XG4gICAgaWYgKCF2aWV3KSByZXR1cm47XG4gICAgY29uc3QgcmVjdCA9IHRoaXMudmlld1JlY3QoKTtcbiAgICBpZiAoIXJlY3QpIHtcbiAgICAgIHRoaXMud2FudGVkID0gW107XG4gICAgICB0aGlzLmRyYXcoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaW5mbyA9IHZpZXcuc291cmNlLmluZm87XG4gICAgY29uc3QgbGV2ZWwgPSByZWdpb25MZXZlbEZvcih0aGlzLnNjYWxlKCksIGluZm8ubGV2ZWxzKTtcbiAgICB0aGlzLndhbnRlZCA9IHJlZ2lvblRpbGVzSW5SZWN0KHJlY3QsIGxldmVsLCBpbmZvLnRpbGVTaXplLCBpbmZvLmJvdW5kcywgU09VUkNFX01BWF9USUxFUyk7XG4gICAgdGhpcy5zY2hlZHVsZURyYXcoKTtcbiAgICBjb25zdCBtaXNzaW5nID0gdGhpcy53YW50ZWQuZmlsdGVyKChrKSA9PiAhdGhpcy50aWxlcy5oYXMocmVnaW9uVGlsZUlkKGspKSk7XG4gICAgdGhpcy5sb2FkaW5nPy5hYm9ydCgpO1xuICAgIHRoaXMubG9hZGluZyA9IG51bGw7XG4gICAgaWYgKCFtaXNzaW5nLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IGxvYWRpbmcgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgdGhpcy5sb2FkaW5nID0gbG9hZGluZztcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBtaXNzaW5nKSB7XG4gICAgICB2aWV3LnNvdXJjZS5nZXRUaWxlKHZpZXcucGxhbmUsIGtleSwgbG9hZGluZy5zaWduYWwpLnRoZW4oXG4gICAgICAgICh0aWxlKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMudmlldz8uc291cmNlICE9PSB2aWV3LnNvdXJjZSB8fCB0aGlzLnZpZXcucGxhbmUgIT09IHZpZXcucGxhbmUpIHJldHVybjtcbiAgICAgICAgICB0aGlzLmtlZXAodGlsZSk7XG4gICAgICAgICAgdGhpcy5zY2hlZHVsZURyYXcoKTtcbiAgICAgICAgfSxcbiAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgIGlmICghaXNBYm9ydEVycm9yKGVycikpIGNvbnNvbGUud2FybignW3JlZ2lvbnNdIHJlZ2lvbiB0aWxlIGZhaWxlZCcsIGVycik7XG4gICAgICAgIH0sXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUga2VlcCh0aWxlOiBSZWdpb25UaWxlKTogdm9pZCB7XG4gICAgY29uc3QgaWQgPSByZWdpb25UaWxlSWQodGlsZSk7XG4gICAgdGhpcy50aWxlcy5kZWxldGUoaWQpO1xuICAgIHRoaXMudGlsZXMuc2V0KGlkLCB0aWxlKTtcbiAgICB3aGlsZSAodGhpcy50aWxlcy5zaXplID4gTEFZRVJfVElMRV9MSU1JVCkgdGhpcy50aWxlcy5kZWxldGUodGhpcy50aWxlcy5rZXlzKCkubmV4dCgpLnZhbHVlIGFzIHN0cmluZyk7XG4gIH1cblxuICBwcml2YXRlIHNjaGVkdWxlRHJhdygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kcmF3RnJhbWUgIT09IG51bGwpIHJldHVybjtcbiAgICB0aGlzLmRyYXdGcmFtZSA9IHJlcXVlc3RGcmFtZSgoKSA9PiB7XG4gICAgICB0aGlzLmRyYXdGcmFtZSA9IG51bGw7XG4gICAgICB0aGlzLmRyYXcoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWJ1aWxkIHRoZSBwYXRocyBmcm9tIHRoZSB3YW50ZWQgdGlsZXMgdGhhdCBhcmUgbG9hZGVkLCBhIG1pc3NpbmcgdGlsZSdzIG5lYXJlc3QgbG9hZGVkXG4gICAqIGFuY2VzdG9yIHN0YW5kaW5nIGluIGZvciBpdDsgZWFjaCBmZWF0dXJlIG9uY2UsIGF0IHRoZSBmaW5lc3QgbGV2ZWwgbG9hZGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmF3KCk6IHZvaWQge1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXc7XG4gICAgY29uc3QgZHJhd24gPSBuZXcgTWFwPHN0cmluZywgVGlsZUZlYXR1cmU+KCk7XG4gICAgY29uc3QgbGV2ZWwgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIGlmICh2aWV3KSB7XG4gICAgICBjb25zdCB1c2VkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiB0aGlzLndhbnRlZCkge1xuICAgICAgICBjb25zdCB0aWxlID0gdGhpcy5sb2FkZWRPckFuY2VzdG9yKGtleSk7XG4gICAgICAgIGlmICghdGlsZSB8fCB1c2VkLmhhcyhyZWdpb25UaWxlSWQodGlsZSkpKSBjb250aW51ZTtcbiAgICAgICAgdXNlZC5hZGQocmVnaW9uVGlsZUlkKHRpbGUpKTtcbiAgICAgICAgZm9yIChjb25zdCBmIG9mIHRpbGUuZmVhdHVyZXMpIHtcbiAgICAgICAgICBpZiAodmlldy50YWtlbi5oYXMoZi5pZCkgfHwgdmlldy5pc0hpZGRlbj8uKGYubGFiZWwpKSBjb250aW51ZTtcbiAgICAgICAgICBjb25zdCBoYWQgPSBsZXZlbC5nZXQoZi5pZCk7XG4gICAgICAgICAgaWYgKGhhZCAhPT0gdW5kZWZpbmVkICYmIGhhZCA8PSB0aWxlLmxldmVsKSBjb250aW51ZTtcbiAgICAgICAgICBkcmF3bi5zZXQoZi5pZCwgZik7XG4gICAgICAgICAgbGV2ZWwuc2V0KGYuaWQsIHRpbGUubGV2ZWwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuZHJhd24gPSBkcmF3bjtcbiAgICBjb25zdCBmaWxsZWQgPSAhIXZpZXcgJiYgaXNGaWxsZWQodmlldy5zdHlsZSk7XG4gICAgY29uc3QgZnJhZyA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcbiAgICBmb3IgKGNvbnN0IHJ1biBvZiB0aGlzLnJ1bnMoZHJhd24sIGZpbGxlZCkpIHtcbiAgICAgIGNvbnN0IHBhdGggPSBzdmdFbCgncGF0aCcpO1xuICAgICAgcGF0aC5zZXRBdHRyaWJ1dGUoJ2QnLCBydW4uZmVhdHVyZXMuZmxhdE1hcCgoZikgPT4gZi5yaW5ncy5tYXAoKHIpID0+IHJpbmdEKHIsICFmLm9wZW4pKSkuam9pbignJykpO1xuICAgICAgcGF0aC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtcnVsZScsICdldmVub2RkJyk7XG4gICAgICBwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWxpbmVqb2luJywgJ3JvdW5kJyk7XG4gICAgICBwYXRoLnNldEF0dHJpYnV0ZSgndmVjdG9yLWVmZmVjdCcsICdub24tc2NhbGluZy1zdHJva2UnKTtcbiAgICAgIGlmIChmaWxsZWQgJiYgdmlldykge1xuICAgICAgICBjb25zdCBwYWludCA9IHNoYXBlUGFpbnQocnVuLmNvbG9yLCBmYWxzZSwgdmlldy5zdHlsZSk7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgcGFpbnQuZmlsbCk7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdmaWxsLW9wYWNpdHknLCBgJHtwYWludC5maWxsT3BhY2l0eX1gKTtcbiAgICAgICAgcGF0aC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsIHBhaW50LnN0cm9rZSk7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCBgJHtwYWludC5zdHJva2VXaWR0aH1gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgJ25vbmUnKTtcbiAgICAgICAgcGF0aC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZScsIHJ1bi5jb2xvcik7XG4gICAgICAgIHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utd2lkdGgnLCBgJHtTT1VSQ0VfU1RST0tFX1BYfWApO1xuICAgICAgfVxuICAgICAgZnJhZy5hcHBlbmRDaGlsZChwYXRoKTtcbiAgICB9XG4gICAgd2hpbGUgKHRoaXMuZ3JvdXAuZmlyc3RDaGlsZCkgdGhpcy5ncm91cC5yZW1vdmVDaGlsZCh0aGlzLmdyb3VwLmZpcnN0Q2hpbGQpO1xuICAgIHRoaXMuZ3JvdXAuYXBwZW5kQ2hpbGQoZnJhZyk7XG4gICAgdGhpcy5hcHBseUNhbWVyYSgpO1xuICAgIHRoaXMuZHJhd0xhYmVscyhmaWxsZWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBkcmF3biBmZWF0dXJlcyBhcyBwYXRoczogb25lIHBlciBjb2xvdXIgd2hlbiBvdXRsaW5lZDsgZmlsbGVkLCBpbiBwYWludCBvcmRlciDigJQgcGFyZW50c1xuICAgKiAoYnkgdGhlIGNsYXNzIGhpZXJhcmNoeSkgYW5kIHRoZW4gbGFyZ2VyIGZlYXR1cmVzIGZpcnN0LCBzbyB3aGF0IGxpZXMgaW5zaWRlIHBhaW50cyBvdmVyXG4gICAqIHRoZW0g4oCUIG9uZSBwYXRoIHBlciBydW4gb2YgYSBjb2xvdXIuXG4gICAqL1xuICBwcml2YXRlIHJ1bnMoXG4gICAgZHJhd246IE1hcDxzdHJpbmcsIFRpbGVGZWF0dXJlPixcbiAgICBmaWxsZWQ6IGJvb2xlYW4sXG4gICk6IEFycmF5PHsgY29sb3I6IHN0cmluZzsgZmVhdHVyZXM6IFRpbGVGZWF0dXJlW10gfT4ge1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLnZpZXc7XG4gICAgY29uc3QgY29sb3JPZiA9IChmOiBUaWxlRmVhdHVyZSkgPT4gdmlldz8uY29sb3JPZihmKSA/PyAnIzAwRkZGRic7XG4gICAgaWYgKCFmaWxsZWQpIHtcbiAgICAgIGNvbnN0IGJ5Q29sb3IgPSBuZXcgTWFwPHN0cmluZywgVGlsZUZlYXR1cmVbXT4oKTtcbiAgICAgIGZvciAoY29uc3QgZiBvZiBkcmF3bi52YWx1ZXMoKSkge1xuICAgICAgICBjb25zdCBjb2xvciA9IGNvbG9yT2YoZik7XG4gICAgICAgIGNvbnN0IGxpc3QgPSBieUNvbG9yLmdldChjb2xvcik7XG4gICAgICAgIGlmIChsaXN0KSBsaXN0LnB1c2goZik7XG4gICAgICAgIGVsc2UgYnlDb2xvci5zZXQoY29sb3IsIFtmXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gQXJyYXkuZnJvbShieUNvbG9yLCAoW2NvbG9yLCBmZWF0dXJlc10pID0+ICh7IGNvbG9yLCBmZWF0dXJlcyB9KSk7XG4gICAgfVxuICAgIGNvbnN0IGFyZWEgPSAoZjogVGlsZUZlYXR1cmUpID0+IChmLmJib3hbMl0gLSBmLmJib3hbMF0pICogKGYuYmJveFszXSAtIGYuYmJveFsxXSk7XG4gICAgY29uc3QgZGVwdGggPSAoZjogVGlsZUZlYXR1cmUpID0+IHRoaXMuZGVwdGhPZi5nZXQoZi5sYWJlbCA/PyAnJykgPz8gMDtcbiAgICBjb25zdCBvcmRlciA9IEFycmF5LmZyb20oZHJhd24udmFsdWVzKCkpLnNvcnQoKGEsIGIpID0+IGRlcHRoKGEpIC0gZGVwdGgoYikgfHwgYXJlYShiKSAtIGFyZWEoYSkpO1xuICAgIGNvbnN0IHJ1bnM6IEFycmF5PHsgY29sb3I6IHN0cmluZzsgZmVhdHVyZXM6IFRpbGVGZWF0dXJlW10gfT4gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGYgb2Ygb3JkZXIpIHtcbiAgICAgIGNvbnN0IGNvbG9yID0gY29sb3JPZihmKTtcbiAgICAgIGNvbnN0IGxhc3QgPSBydW5zW3J1bnMubGVuZ3RoIC0gMV07XG4gICAgICBpZiAobGFzdCAmJiBsYXN0LmNvbG9yID09PSBjb2xvcikgbGFzdC5mZWF0dXJlcy5wdXNoKGYpO1xuICAgICAgZWxzZSBydW5zLnB1c2goeyBjb2xvciwgZmVhdHVyZXM6IFtmXSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJ1bnM7XG4gIH1cblxuICAvKiogQ2xhc3MgbGFiZWxzIGluc2lkZSB0aGUgZHJhd24gZmVhdHVyZXMgKGVhY2ggcGFydCB3aGVyZSBpdCBmaXRzKSwgd2hlbiBsYWJlbHMgYXJlIG9uLiAqL1xuICBwcml2YXRlIGRyYXdMYWJlbHMoZmlsbGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5sYWJlbExheWVyLmNsZWFyKCk7XG4gICAgY29uc3QgdmlldyA9IHRoaXMudmlldztcbiAgICBpZiAoIXZpZXc/LmxhYmVscykgcmV0dXJuO1xuICAgIC8vIE9ubHkgdGhlIGRlZXBlc3QgY2xhc3NlcyBkcmF3biBhcmUgbGFiZWxsZWQ6IGEgY2xhc3Mgd2hvc2Ugc3ViY2xhc3NlcyBhcmUgZHJhd24gdG9vIChhblxuICAgIC8vIGF0bGFzJ3MgXCJJc29jb3J0ZXhcIiB1bmRlciBpdHMgYXJlYXMpIHdvdWxkIG9ubHkgcmVwZWF0IG92ZXIgdGhlbS5cbiAgICBjb25zdCBjb3ZlcmVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBmIG9mIHRoaXMuZHJhd24udmFsdWVzKCkpIHtcbiAgICAgIGxldCBwID0gZi5sYWJlbCA/IHRoaXMucGFyZW50T2YuZ2V0KGYubGFiZWwpIDogdW5kZWZpbmVkO1xuICAgICAgd2hpbGUgKHAgJiYgIWNvdmVyZWQuaGFzKHApKSB7XG4gICAgICAgIGNvdmVyZWQuYWRkKHApO1xuICAgICAgICBwID0gdGhpcy5wYXJlbnRPZi5nZXQocCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgZiBvZiB0aGlzLmRyYXduLnZhbHVlcygpKSB7XG4gICAgICBjb25zdCBhdCA9IGYubGFiZWxzO1xuICAgICAgaWYgKCFhdCB8fCAhZi5sYWJlbCB8fCBjb3ZlcmVkLmhhcyhmLmxhYmVsKSkgY29udGludWU7XG4gICAgICBjb25zdCBjb2xvciA9IGZpbGxlZCA/ICcjMTExJyA6IHZpZXcuY29sb3JPZihmKTtcbiAgICAgIGZvciAobGV0IGsgPSAwOyBrICsgMiA8IGF0Lmxlbmd0aDsgayArPSAzKSB7XG4gICAgICAgIHBsYWNlSW5zaWRlTGFiZWwodGhpcy5sYWJlbExheWVyLCBmLmxhYmVsLCB7IHg6IGF0W2tdLCB5OiBhdFtrICsgMV0sIHJvb206IGF0W2sgKyAyXSB9LCBjb2xvcik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIFRoZSBsb2FkZWQgdGlsZSBmb3IgYGtleWAsIGVsc2UgaXRzIG5lYXJlc3QgbG9hZGVkIGNvYXJzZXIgYW5jZXN0b3IuICovXG4gIHByaXZhdGUgbG9hZGVkT3JBbmNlc3RvcihrZXk6IFJlZ2lvblRpbGVLZXkpOiBSZWdpb25UaWxlIHwgbnVsbCB7XG4gICAgY29uc3QgbGV2ZWxzID0gdGhpcy52aWV3Py5zb3VyY2UuaW5mby5sZXZlbHMgPz8gMDtcbiAgICBsZXQgeyBneCwgZ3kgfSA9IGtleTtcbiAgICBmb3IgKGxldCBsZXZlbCA9IGtleS5sZXZlbDsgbGV2ZWwgPCBsZXZlbHM7IGxldmVsKyspIHtcbiAgICAgIGNvbnN0IHRpbGUgPSB0aGlzLnRpbGVzLmdldChyZWdpb25UaWxlSWQoeyBsZXZlbCwgZ3gsIGd5IH0pKTtcbiAgICAgIGlmICh0aWxlKSByZXR1cm4gdGlsZTtcbiAgICAgIGd4ID0gTWF0aC5mbG9vcihneCAvIDIpO1xuICAgICAgZ3kgPSBNYXRoLmZsb29yKGd5IC8gMik7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbi8qKiBQYXRoIGRhdGEgb2Ygb25lIHJpbmcgKGBjbG9zZWRgKSBvciBwb2x5bGluZSwgaW4gd29ybGQgdW5pdHMgdG8gMS8xMDAuICovXG5mdW5jdGlvbiByaW5nRChyaW5nOiBGbG9hdDMyQXJyYXksIGNsb3NlZDogYm9vbGVhbik6IHN0cmluZyB7XG4gIGNvbnN0IG4gPSByaW5nLmxlbmd0aCA+PiAxO1xuICBpZiAobiA8IDIpIHJldHVybiAnJztcbiAgbGV0IGQgPSBgTSR7cjIocmluZ1swXSl9ICR7cjIocmluZ1sxXSl9YDtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBuOyBpKyspIGQgKz0gYEwke3IyKHJpbmdbMiAqIGldKX0gJHtyMihyaW5nWzIgKiBpICsgMV0pfWA7XG4gIHJldHVybiBjbG9zZWQgPyBgJHtkfVpgIDogZDtcbn1cblxuZnVuY3Rpb24gcjIodjogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQodiAqIDEwMCkgLyAxMDA7XG59XG5cbmZ1bmN0aW9uIHN2Z1NpemUoc3ZnOiBTVkdTVkdFbGVtZW50KTogeyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHtcbiAgY29uc3Qgd2lkdGggPSBzdmcuY2xpZW50V2lkdGggfHwgc3ZnLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xuICBjb25zdCBoZWlnaHQgPSBzdmcuY2xpZW50SGVpZ2h0IHx8IHN2Zy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gIHJldHVybiB7IHdpZHRoLCBoZWlnaHQgfTtcbn1cblxuY29uc3QgcmVxdWVzdEZyYW1lID0gKGZuOiAoKSA9PiB2b2lkKTogbnVtYmVyID0+XG4gIHR5cGVvZiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPT09ICdmdW5jdGlvbidcbiAgICA/IHJlcXVlc3RBbmltYXRpb25GcmFtZShmbilcbiAgICA6IChzZXRUaW1lb3V0KGZuLCAxNikgYXMgdW5rbm93biBhcyBudW1iZXIpO1xuXG5jb25zdCBjYW5jZWxGcmFtZSA9IChpZDogbnVtYmVyKTogdm9pZCA9PlxuICB0eXBlb2YgY2FuY2VsQW5pbWF0aW9uRnJhbWUgPT09ICdmdW5jdGlvbicgPyBjYW5jZWxBbmltYXRpb25GcmFtZShpZCkgOiBjbGVhclRpbWVvdXQoaWQpO1xuXG4vKiogRGVwdGggb2YgZWFjaCBjbGFzcyBpbiBhIGNsYXNzIGhpZXJhcmNoeSAoYSByb290IGlzIDApOyBlbXB0eSB3aXRob3V0IG9uZS4gKi9cbmZ1bmN0aW9uIGhpZXJhcmNoeURlcHRocyhcbiAgaGllcmFyY2h5OiBSZWFkb25seUFycmF5PHsgbmFtZTogc3RyaW5nOyBwYXJlbnQ/OiBzdHJpbmcgfCBudWxsIH0+IHwgdW5kZWZpbmVkLFxuKTogTWFwPHN0cmluZywgbnVtYmVyPiB7XG4gIGNvbnN0IGRlcHRocyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gIGlmICghaGllcmFyY2h5KSByZXR1cm4gZGVwdGhzO1xuICBjb25zdCBwYXJlbnQgPSBuZXcgTWFwKGhpZXJhcmNoeS5tYXAoKG4pID0+IFtuLm5hbWUsIG4ucGFyZW50ID8/IG51bGxdKSk7XG4gIGZvciAoY29uc3QgbiBvZiBoaWVyYXJjaHkpIHtcbiAgICBsZXQgZCA9IDA7XG4gICAgbGV0IHAgPSBwYXJlbnQuZ2V0KG4ubmFtZSk7XG4gICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPihbbi5uYW1lXSk7XG4gICAgd2hpbGUgKHAgJiYgIXNlZW4uaGFzKHApKSB7XG4gICAgICBzZWVuLmFkZChwKTtcbiAgICAgIGQrKztcbiAgICAgIHAgPSBwYXJlbnQuZ2V0KHApID8/IG51bGw7XG4gICAgfVxuICAgIGRlcHRocy5zZXQobi5uYW1lLCBkKTtcbiAgfVxuICByZXR1cm4gZGVwdGhzO1xufVxuIl19
@@ -0,0 +1,97 @@
1
+ /**
2
+ * How regions are drawn, shared by the OpenSeadragon and napari overlays and the region-source
3
+ * layer, so a feature looks the same before and after it is taken into the regions.
4
+ *
5
+ * Two looks: **outlines** (the default — each region stroked in its colour, filled only while
6
+ * selected) and **filled**, an atlas's look (each region filled in its colour, with thin outlines,
7
+ * the selection in a highlight colour, labels centred inside each part).
8
+ */
9
+ import { MultiPolygon, Polygon, Rectangle } from '../models/region';
10
+ import { polylabel } from '../geometry/polylabel';
11
+ import { svgEl } from './svg-region-renderer';
12
+ export const DEFAULT_REGION_STYLE = {
13
+ fillOpacity: 0,
14
+ stroke: null,
15
+ strokeWidth: null,
16
+ highlight: null,
17
+ };
18
+ /** A selected region's fill in the filled look, unless the style names one (the Allen atlas's). */
19
+ export const DEFAULT_HIGHLIGHT = '#a020f0';
20
+ /** Whether `style` is the filled look. */
21
+ export function isFilled(style) {
22
+ return style.fillOpacity > 0;
23
+ }
24
+ /** The paint of a region of colour `color`, selected or not, in `style`. */
25
+ export function shapePaint(color, selected, style = DEFAULT_REGION_STYLE) {
26
+ if (!isFilled(style)) {
27
+ return selected
28
+ ? { fill: color, fillOpacity: 0.35, stroke: color, strokeWidth: 4 }
29
+ : { fill: 'none', fillOpacity: 0, stroke: color, strokeWidth: 2 };
30
+ }
31
+ const width = style.strokeWidth ?? 1;
32
+ return selected
33
+ ? {
34
+ fill: style.highlight ?? DEFAULT_HIGHLIGHT,
35
+ fillOpacity: Math.max(style.fillOpacity, 0.85),
36
+ stroke: style.stroke ?? color,
37
+ strokeWidth: width + 1,
38
+ }
39
+ : { fill: color, fillOpacity: style.fillOpacity, stroke: style.stroke ?? color, strokeWidth: width };
40
+ }
41
+ /** Set `paint` on an SVG shape. */
42
+ export function applyPaint(el, paint) {
43
+ el.setAttribute('fill', paint.fill);
44
+ el.setAttribute('fill-opacity', `${paint.fillOpacity}`);
45
+ el.setAttribute('stroke', paint.stroke);
46
+ el.setAttribute('stroke-width', `${paint.strokeWidth}`);
47
+ }
48
+ /** Where to label `region`: each part's pole of inaccessibility (a rectangle's centre). */
49
+ export function regionLabelSpots(region) {
50
+ const b = region.bounds;
51
+ if (b instanceof Rectangle) {
52
+ const room = Math.min(Math.abs(b.width), Math.abs(b.height)) / 2;
53
+ return [{ x: b.x + b.width / 2, y: b.y + b.height / 2, room }];
54
+ }
55
+ const parts = b instanceof MultiPolygon ? b.polygons : b instanceof Polygon && b.closed !== false ? [b] : [];
56
+ const spots = [];
57
+ for (const p of parts) {
58
+ const rings = [Float64Array.from(p.xpoints.flatMap((x, i) => [x, p.ypoints[i]]))];
59
+ for (const hole of p.holes ?? [])
60
+ rings.push(Float64Array.from(hole.flat()));
61
+ const pole = polylabel(rings);
62
+ if (pole && pole.distance > 0)
63
+ spots.push({ x: pole.x, y: pole.y, room: pole.distance });
64
+ }
65
+ return spots;
66
+ }
67
+ /** Font size of a centred label, px. */
68
+ const INSIDE_LABEL_PX = 10;
69
+ /**
70
+ * A class label centred at `spot`, shown only while it fits: the room around the spot, on screen,
71
+ * at least half the text's width (and a few pixels). Re-checked on every camera move.
72
+ */
73
+ export function placeInsideLabel(layer, text, spot, color = '#111') {
74
+ const el = svgEl('text');
75
+ el.setAttribute('fill', color);
76
+ el.setAttribute('font-size', `${INSIDE_LABEL_PX}`);
77
+ el.setAttribute('font-family', 'sans-serif');
78
+ el.setAttribute('text-anchor', 'middle');
79
+ el.setAttribute('dominant-baseline', 'central');
80
+ el.setAttribute('pointer-events', 'none');
81
+ el.textContent = text;
82
+ const halfWidth = (text.length * INSIDE_LABEL_PX * 0.6) / 2;
83
+ return layer.place(el, (e, project) => {
84
+ const [sx, sy] = project(spot.x, spot.y);
85
+ e.setAttribute('x', `${sx}`);
86
+ e.setAttribute('y', `${sy}`);
87
+ e.style.display = labelFits(project, spot, halfWidth) ? '' : 'none';
88
+ });
89
+ }
90
+ /** Whether a label `halfWidth` px wide fits around `spot` through `project`. */
91
+ export function labelFits(project, spot, halfWidth) {
92
+ const [ax, ay] = project(spot.x, spot.y);
93
+ const [bx, by] = project(spot.x + spot.room, spot.y);
94
+ const roomPx = Math.hypot(bx - ax, by - ay);
95
+ return roomPx >= Math.max(halfWidth * 0.8, INSIDE_LABEL_PX * 0.6);
96
+ }
97
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXN0eWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9yZWdpb24tb3ZlcmxheS9yZWdpb24tc3R5bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUNILE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBVSxNQUFNLGtCQUFrQixDQUFDO0FBQzVFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFjOUMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQWdCO0lBQy9DLFdBQVcsRUFBRSxDQUFDO0lBQ2QsTUFBTSxFQUFFLElBQUk7SUFDWixXQUFXLEVBQUUsSUFBSTtJQUNqQixTQUFTLEVBQUUsSUFBSTtDQUNoQixDQUFDO0FBRUYsbUdBQW1HO0FBQ25HLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLFNBQVMsQ0FBQztBQUUzQywwQ0FBMEM7QUFDMUMsTUFBTSxVQUFVLFFBQVEsQ0FBQyxLQUFrQjtJQUN6QyxPQUFPLEtBQUssQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFVRCw0RUFBNEU7QUFDNUUsTUFBTSxVQUFVLFVBQVUsQ0FDeEIsS0FBYSxFQUNiLFFBQWlCLEVBQ2pCLFFBQXFCLG9CQUFvQjtJQUV6QyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDckIsT0FBTyxRQUFRO1lBQ2IsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRTtZQUNuRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFB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bnMgYXJlIGRyYXduLCBzaGFyZWQgYnkgdGhlIE9wZW5TZWFkcmFnb24gYW5kIG5hcGFyaSBvdmVybGF5cyBhbmQgdGhlIHJlZ2lvbi1zb3VyY2VcbiAqIGxheWVyLCBzbyBhIGZlYXR1cmUgbG9va3MgdGhlIHNhbWUgYmVmb3JlIGFuZCBhZnRlciBpdCBpcyB0YWtlbiBpbnRvIHRoZSByZWdpb25zLlxuICpcbiAqIFR3byBsb29rczogKipvdXRsaW5lcyoqICh0aGUgZGVmYXVsdCDigJQgZWFjaCByZWdpb24gc3Ryb2tlZCBpbiBpdHMgY29sb3VyLCBmaWxsZWQgb25seSB3aGlsZVxuICogc2VsZWN0ZWQpIGFuZCAqKmZpbGxlZCoqLCBhbiBhdGxhcydzIGxvb2sgKGVhY2ggcmVnaW9uIGZpbGxlZCBpbiBpdHMgY29sb3VyLCB3aXRoIHRoaW4gb3V0bGluZXMsXG4gKiB0aGUgc2VsZWN0aW9uIGluIGEgaGlnaGxpZ2h0IGNvbG91ciwgbGFiZWxzIGNlbnRyZWQgaW5zaWRlIGVhY2ggcGFydCkuXG4gKi9cbmltcG9ydCB7IE11bHRpUG9seWdvbiwgUG9seWdvbiwgUmVjdGFuZ2xlLCBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IHBvbHlsYWJlbCB9IGZyb20gJy4uL2dlb21ldHJ5L3BvbHlsYWJlbCc7XG5pbXBvcnQgdHlwZSB7IFByb2plY3QsIFNjcmVlbkxheWVyIH0gZnJvbSAnLi9zdmctcmVnaW9uLXJlbmRlcmVyJztcbmltcG9ydCB7IHN2Z0VsIH0gZnJvbSAnLi9zdmctcmVnaW9uLXJlbmRlcmVyJztcblxuLyoqIFRoZSByZWdpb24gbG9vayAoc2VlIHRoZSBtb2R1bGUgZG9jKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaW9uU3R5bGUge1xuICAvKiogRmlsbCBlYWNoIHJlZ2lvbiBhdCB0aGlzIG9wYWNpdHk7IDAgZHJhd3Mgb3V0bGluZXMgb25seS4gKi9cbiAgZmlsbE9wYWNpdHk6IG51bWJlcjtcbiAgLyoqIE91dGxpbmUgY29sb3VyIG9mIGEgZmlsbGVkIHJlZ2lvbjsgbnVsbDogaXRzIG93biBjb2xvdXIuICovXG4gIHN0cm9rZTogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIE91dGxpbmUgd2lkdGggb2YgYSBmaWxsZWQgcmVnaW9uLCBzY3JlZW4gcHg7IG51bGw6IDEuICovXG4gIHN0cm9rZVdpZHRoOiBudW1iZXIgfCBudWxsO1xuICAvKiogRmlsbCBjb2xvdXIgb2YgYSBzZWxlY3RlZCBmaWxsZWQgcmVnaW9uOyBudWxsOiB7QGxpbmsgREVGQVVMVF9ISUdITElHSFR9LiAqL1xuICBoaWdobGlnaHQ6IHN0cmluZyB8IG51bGw7XG59XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1JFR0lPTl9TVFlMRTogUmVnaW9uU3R5bGUgPSB7XG4gIGZpbGxPcGFjaXR5OiAwLFxuICBzdHJva2U6IG51bGwsXG4gIHN0cm9rZVdpZHRoOiBudWxsLFxuICBoaWdobGlnaHQ6IG51bGwsXG59O1xuXG4vKiogQSBzZWxlY3RlZCByZWdpb24ncyBmaWxsIGluIHRoZSBmaWxsZWQgbG9vaywgdW5sZXNzIHRoZSBzdHlsZSBuYW1lcyBvbmUgKHRoZSBBbGxlbiBhdGxhcydzKS4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0hJR0hMSUdIVCA9ICcjYTAyMGYwJztcblxuLyoqIFdoZXRoZXIgYHN0eWxlYCBpcyB0aGUgZmlsbGVkIGxvb2suICovXG5leHBvcnQgZnVuY3Rpb24gaXNGaWxsZWQoc3R5bGU6IFJlZ2lvblN0eWxlKTogYm9vbGVhbiB7XG4gIHJldHVybiBzdHlsZS5maWxsT3BhY2l0eSA+IDA7XG59XG5cbi8qKiBUaGUgcGFpbnQgb2Ygb25lIHJlZ2lvbiBzaGFwZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcGVQYWludCB7XG4gIGZpbGw6IHN0cmluZztcbiAgZmlsbE9wYWNpdHk6IG51bWJlcjtcbiAgc3Ryb2tlOiBzdHJpbmc7XG4gIHN0cm9rZVdpZHRoOiBudW1iZXI7XG59XG5cbi8qKiBUaGUgcGFpbnQgb2YgYSByZWdpb24gb2YgY29sb3VyIGBjb2xvcmAsIHNlbGVjdGVkIG9yIG5vdCwgaW4gYHN0eWxlYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFwZVBhaW50KFxuICBjb2xvcjogc3RyaW5nLFxuICBzZWxlY3RlZDogYm9vbGVhbixcbiAgc3R5bGU6IFJlZ2lvblN0eWxlID0gREVGQVVMVF9SRUdJT05fU1RZTEUsXG4pOiBTaGFwZVBhaW50IHtcbiAgaWYgKCFpc0ZpbGxlZChzdHlsZSkpIHtcbiAgICByZXR1cm4gc2VsZWN0ZWRcbiAgICAgID8geyBmaWxsOiBjb2xvciwgZmlsbE9wYWNpdHk6IDAuMzUsIHN0cm9rZTogY29sb3IsIHN0cm9rZVdpZHRoOiA0IH1cbiAgICAgIDogeyBmaWxsOiAnbm9uZScsIGZpbGxPcGFjaXR5OiAwLCBzdHJva2U6IGNvbG9yLCBzdHJva2VXaWR0aDogMiB9O1xuICB9XG4gIGNvbnN0IHdpZHRoID0gc3R5bGUuc3Ryb2tlV2lkdGggPz8gMTtcbiAgcmV0dXJuIHNlbGVjdGVkXG4gICAgPyB7XG4gICAgICAgIGZpbGw6IHN0eWxlLmhpZ2hsaWdodCA/PyBERUZBVUxUX0hJR0hMSUdIVCxcbiAgICAgICAgZmlsbE9wYWNpdHk6IE1hdGgubWF4KHN0eWxlLmZpbGxPcGFjaXR5LCAwLjg1KSxcbiAgICAgICAgc3Ryb2tlOiBzdHlsZS5zdHJva2UgPz8gY29sb3IsXG4gICAgICAgIHN0cm9rZVdpZHRoOiB3aWR0aCArIDEsXG4gICAgICB9XG4gICAgOiB7IGZpbGw6IGNvbG9yLCBmaWxsT3BhY2l0eTogc3R5bGUuZmlsbE9wYWNpdHksIHN0cm9rZTogc3R5bGUuc3Ryb2tlID8/IGNvbG9yLCBzdHJva2VXaWR0aDogd2lkdGggfTtcbn1cblxuLyoqIFNldCBgcGFpbnRgIG9uIGFuIFNWRyBzaGFwZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhaW50KGVsOiBTVkdFbGVtZW50LCBwYWludDogU2hhcGVQYWludCk6IHZvaWQge1xuICBlbC5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCBwYWludC5maWxsKTtcbiAgZWwuc2V0QXR0cmlidXRlKCdmaWxsLW9wYWNpdHknLCBgJHtwYWludC5maWxsT3BhY2l0eX1gKTtcbiAgZWwuc2V0QXR0cmlidXRlKCdzdHJva2UnLCBwYWludC5zdHJva2UpO1xuICBlbC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS13aWR0aCcsIGAke3BhaW50LnN0cm9rZVdpZHRofWApO1xufVxuXG4vKiogQSBwb2ludCB0byBsYWJlbCBhIHBhcnQgYXQsIGFuZCB0aGUgcm9vbSBhcm91bmQgaXQgKGltYWdlIHB4KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGFiZWxTcG90IHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG4gIHJvb206IG51bWJlcjtcbn1cblxuLyoqIFdoZXJlIHRvIGxhYmVsIGByZWdpb25gOiBlYWNoIHBhcnQncyBwb2xlIG9mIGluYWNjZXNzaWJpbGl0eSAoYSByZWN0YW5nbGUncyBjZW50cmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lvbkxhYmVsU3BvdHMocmVnaW9uOiBSZWdpb24pOiBMYWJlbFNwb3RbXSB7XG4gIGNvbnN0IGIgPSByZWdpb24uYm91bmRzO1xuICBpZiAoYiBpbnN0YW5jZW9mIFJlY3RhbmdsZSkge1xuICAgIGNvbnN0IHJvb20gPSBNYXRoLm1pbihNYXRoLmFicyhiLndpZHRoKSwgTWF0aC5hYnMoYi5oZWlnaHQpKSAvIDI7XG4gICAgcmV0dXJuIFt7IHg6IGIueCArIGIud2lkdGggLyAyLCB5OiBiLnkgKyBiLmhlaWdodCAvIDIsIHJvb20gfV07XG4gIH1cbiAgY29uc3QgcGFydHMgPSBiIGluc3RhbmNlb2YgTXVsdGlQb2x5Z29uID8gYi5wb2x5Z29ucyA6IGIgaW5zdGFuY2VvZiBQb2x5Z29uICYmIGIuY2xvc2VkICE9PSBmYWxzZSA/IFtiXSA6IFtdO1xuICBjb25zdCBzcG90czogTGFiZWxTcG90W10gPSBbXTtcbiAgZm9yIChjb25zdCBwIG9mIHBhcnRzKSB7XG4gICAgY29uc3QgcmluZ3M6IEZsb2F0NjRBcnJheVtdID0gW0Zsb2F0NjRBcnJheS5mcm9tKHAueHBvaW50cy5mbGF0TWFwKCh4LCBpKSA9PiBbeCwgcC55cG9pbnRzW2ldXSkpXTtcbiAgICBmb3IgKGNvbnN0IGhvbGUgb2YgcC5ob2xlcyA/PyBbXSkgcmluZ3MucHVzaChGbG9hdDY0QXJyYXkuZnJvbShob2xlLmZsYXQoKSkpO1xuICAgIGNvbnN0IHBvbGUgPSBwb2x5bGFiZWwocmluZ3MpO1xuICAgIGlmIChwb2xlICYmIHBvbGUuZGlzdGFuY2UgPiAwKSBzcG90cy5wdXNoKHsgeDogcG9sZS54LCB5OiBwb2xlLnksIHJvb206IHBvbGUuZGlzdGFuY2UgfSk7XG4gIH1cbiAgcmV0dXJuIHNwb3RzO1xufVxuXG4vKiogRm9udCBzaXplIG9mIGEgY2VudHJlZCBsYWJlbCwgcHguICovXG5jb25zdCBJTlNJREVfTEFCRUxfUFggPSAxMDtcblxuLyoqXG4gKiBBIGNsYXNzIGxhYmVsIGNlbnRyZWQgYXQgYHNwb3RgLCBzaG93biBvbmx5IHdoaWxlIGl0IGZpdHM6IHRoZSByb29tIGFyb3VuZCB0aGUgc3BvdCwgb24gc2NyZWVuLFxuICogYXQgbGVhc3QgaGFsZiB0aGUgdGV4dCdzIHdpZHRoIChhbmQgYSBmZXcgcGl4ZWxzKS4gUmUtY2hlY2tlZCBvbiBldmVyeSBjYW1lcmEgbW92ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBsYWNlSW5zaWRlTGFiZWwoXG4gIGxheWVyOiBTY3JlZW5MYXllcixcbiAgdGV4dDogc3RyaW5nLFxuICBzcG90OiBMYWJlbFNwb3QsXG4gIGNvbG9yID0gJyMxMTEnLFxuKTogU1ZHVGV4dEVsZW1lbnQge1xuICBjb25zdCBlbCA9IHN2Z0VsKCd0ZXh0Jyk7XG4gIGVsLnNldEF0dHJpYnV0ZSgnZmlsbCcsIGNvbG9yKTtcbiAgZWwuc2V0QXR0cmlidXRlKCdmb250LXNpemUnLCBgJHtJTlNJREVfTEFCRUxfUFh9YCk7XG4gIGVsLnNldEF0dHJpYnV0ZSgnZm9udC1mYW1pbHknLCAnc2Fucy1zZXJpZicpO1xuICBlbC5zZXRBdHRyaWJ1dGUoJ3RleHQtYW5jaG9yJywgJ21pZGRsZScpO1xuICBlbC5zZXRBdHRyaWJ1dGUoJ2RvbWluYW50LWJhc2VsaW5lJywgJ2NlbnRyYWwnKTtcbiAgZWwuc2V0QXR0cmlidXRlKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG4gIGVsLnRleHRDb250ZW50ID0gdGV4dDtcbiAgY29uc3QgaGFsZldpZHRoID0gKHRleHQubGVuZ3RoICogSU5TSURFX0xBQkVMX1BYICogMC42KSAvIDI7XG4gIHJldHVybiBsYXllci5wbGFjZShlbCwgKGUsIHByb2plY3QpID0+IHtcbiAgICBjb25zdCBbc3gsIHN5XSA9IHByb2plY3Qoc3BvdC54LCBzcG90LnkpO1xuICAgIGUuc2V0QXR0cmlidXRlKCd4JywgYCR7c3h9YCk7XG4gICAgZS5zZXRBdHRyaWJ1dGUoJ3knLCBgJHtzeX1gKTtcbiAgICBlLnN0eWxlLmRpc3BsYXkgPSBsYWJlbEZpdHMocHJvamVjdCwgc3BvdCwgaGFsZldpZHRoKSA/ICcnIDogJ25vbmUnO1xuICB9KTtcbn1cblxuLyoqIFdoZXRoZXIgYSBsYWJlbCBgaGFsZldpZHRoYCBweCB3aWRlIGZpdHMgYXJvdW5kIGBzcG90YCB0aHJvdWdoIGBwcm9qZWN0YC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYWJlbEZpdHMocHJvamVjdDogUHJvamVjdCwgc3BvdDogTGFiZWxTcG90LCBoYWxmV2lkdGg6IG51bWJlcik6IGJvb2xlYW4ge1xuICBjb25zdCBbYXgsIGF5XSA9IHByb2plY3Qoc3BvdC54LCBzcG90LnkpO1xuICBjb25zdCBbYngsIGJ5XSA9IHByb2plY3Qoc3BvdC54ICsgc3BvdC5yb29tLCBzcG90LnkpO1xuICBjb25zdCByb29tUHggPSBNYXRoLmh5cG90KGJ4IC0gYXgsIGJ5IC0gYXkpO1xuICByZXR1cm4gcm9vbVB4ID49IE1hdGgubWF4KGhhbGZXaWR0aCAqIDAuOCwgSU5TSURFX0xBQkVMX1BYICogMC42KTtcbn1cbiJdfQ==