@react-x11/components 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -4
- package/dist/charts/components.d.ts +3 -1
- package/dist/charts/components.d.ts.map +1 -1
- package/dist/charts/components.js +8 -4
- package/dist/charts/components.js.map +1 -1
- package/dist/charts/node.d.ts +13 -6
- package/dist/charts/node.d.ts.map +1 -1
- package/dist/charts/node.js +75 -24
- package/dist/charts/node.js.map +1 -1
- package/dist/charts/render.d.ts +4 -0
- package/dist/charts/render.d.ts.map +1 -1
- package/dist/charts/render.js +11 -6
- package/dist/charts/render.js.map +1 -1
- package/dist/code-editor/node.d.ts +47 -16
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +121 -51
- package/dist/code-editor/node.js.map +1 -1
- package/dist/flow/draw.d.ts +19 -1
- package/dist/flow/draw.d.ts.map +1 -1
- package/dist/flow/draw.js +64 -35
- package/dist/flow/draw.js.map +1 -1
- package/dist/flow/index.d.ts.map +1 -1
- package/dist/flow/index.js +24 -8
- package/dist/flow/index.js.map +1 -1
- package/dist/flow/model.d.ts +4 -2
- package/dist/flow/model.d.ts.map +1 -1
- package/dist/flow/model.js +4 -2
- package/dist/flow/model.js.map +1 -1
- package/dist/flow/node.d.ts +40 -9
- package/dist/flow/node.d.ts.map +1 -1
- package/dist/flow/node.js +142 -53
- package/dist/flow/node.js.map +1 -1
- package/dist/flow/types.d.ts +46 -21
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/formula/index.d.ts +4 -2
- package/dist/formula/index.d.ts.map +1 -1
- package/dist/formula/index.js.map +1 -1
- package/dist/formula/node.d.ts +5 -1
- package/dist/formula/node.d.ts.map +1 -1
- package/dist/formula/node.js +19 -3
- package/dist/formula/node.js.map +1 -1
- package/dist/html/controls.d.ts +4 -1
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/cascade.d.ts +11 -5
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +18 -8
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/parse.d.ts +15 -10
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +41 -16
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +3 -0
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +3 -1
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/values.d.ts +14 -1
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +11 -8
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +1 -0
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +12 -5
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +7 -4
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +22 -1
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/node.d.ts +22 -8
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +97 -15
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +3 -0
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +2 -2
- package/dist/html/paint.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/dist/maps/clip.d.ts +43 -0
- package/dist/maps/clip.d.ts.map +1 -0
- package/dist/maps/clip.js +171 -0
- package/dist/maps/clip.js.map +1 -0
- package/dist/maps/gzip.d.ts +15 -0
- package/dist/maps/gzip.d.ts.map +1 -0
- package/dist/maps/gzip.js +56 -0
- package/dist/maps/gzip.js.map +1 -0
- package/dist/maps/index.d.ts +55 -0
- package/dist/maps/index.d.ts.map +1 -0
- package/dist/maps/index.js +141 -0
- package/dist/maps/index.js.map +1 -0
- package/dist/maps/labels.d.ts +123 -0
- package/dist/maps/labels.d.ts.map +1 -0
- package/dist/maps/labels.js +323 -0
- package/dist/maps/labels.js.map +1 -0
- package/dist/maps/mvt.d.ts +244 -0
- package/dist/maps/mvt.d.ts.map +1 -0
- package/dist/maps/mvt.js +820 -0
- package/dist/maps/mvt.js.map +1 -0
- package/dist/maps/node.d.ts +278 -0
- package/dist/maps/node.d.ts.map +1 -0
- package/dist/maps/node.js +1459 -0
- package/dist/maps/node.js.map +1 -0
- package/dist/maps/overlay.d.ts +157 -0
- package/dist/maps/overlay.d.ts.map +1 -0
- package/dist/maps/overlay.js +472 -0
- package/dist/maps/overlay.js.map +1 -0
- package/dist/maps/paint.d.ts +226 -0
- package/dist/maps/paint.d.ts.map +1 -0
- package/dist/maps/paint.js +705 -0
- package/dist/maps/paint.js.map +1 -0
- package/dist/maps/proj.d.ts +281 -0
- package/dist/maps/proj.d.ts.map +1 -0
- package/dist/maps/proj.js +451 -0
- package/dist/maps/proj.js.map +1 -0
- package/dist/maps/sources.d.ts +256 -0
- package/dist/maps/sources.d.ts.map +1 -0
- package/dist/maps/sources.js +210 -0
- package/dist/maps/sources.js.map +1 -0
- package/dist/maps/style.d.ts +141 -0
- package/dist/maps/style.d.ts.map +1 -0
- package/dist/maps/style.js +147 -0
- package/dist/maps/style.js.map +1 -0
- package/dist/maps/styles.d.ts +82 -0
- package/dist/maps/styles.d.ts.map +1 -0
- package/dist/maps/styles.js +898 -0
- package/dist/maps/styles.js.map +1 -0
- package/dist/maps/tiles.d.ts +283 -0
- package/dist/maps/tiles.d.ts.map +1 -0
- package/dist/maps/tiles.js +469 -0
- package/dist/maps/tiles.js.map +1 -0
- package/dist/maps/types.d.ts +244 -0
- package/dist/maps/types.d.ts.map +1 -0
- package/dist/maps/types.js +2 -0
- package/dist/maps/types.js.map +1 -0
- package/dist/qml/containers.d.ts +3 -0
- package/dist/qml/containers.d.ts.map +1 -0
- package/dist/qml/containers.js +331 -0
- package/dist/qml/containers.js.map +1 -0
- package/dist/qml/controls.d.ts +12 -0
- package/dist/qml/controls.d.ts.map +1 -0
- package/dist/qml/controls.js +21 -0
- package/dist/qml/controls.js.map +1 -0
- package/dist/qml/globals.d.ts +6 -0
- package/dist/qml/globals.d.ts.map +1 -0
- package/dist/qml/globals.js +25 -0
- package/dist/qml/globals.js.map +1 -0
- package/dist/qml/index.d.ts +15 -0
- package/dist/qml/index.d.ts.map +1 -0
- package/dist/qml/index.js +25 -0
- package/dist/qml/index.js.map +1 -0
- package/dist/qml/interaction.d.ts +12 -0
- package/dist/qml/interaction.d.ts.map +1 -0
- package/dist/qml/interaction.js +246 -0
- package/dist/qml/interaction.js.map +1 -0
- package/dist/qml/ir.d.ts +106 -0
- package/dist/qml/ir.d.ts.map +1 -0
- package/dist/qml/ir.js +7 -0
- package/dist/qml/ir.js.map +1 -0
- package/dist/qml/layouts.d.ts +3 -0
- package/dist/qml/layouts.d.ts.map +1 -0
- package/dist/qml/layouts.js +122 -0
- package/dist/qml/layouts.js.map +1 -0
- package/dist/qml/models.d.ts +14 -0
- package/dist/qml/models.d.ts.map +1 -0
- package/dist/qml/models.js +80 -0
- package/dist/qml/models.js.map +1 -0
- package/dist/qml/objects.d.ts +228 -0
- package/dist/qml/objects.d.ts.map +1 -0
- package/dist/qml/objects.js +1103 -0
- package/dist/qml/objects.js.map +1 -0
- package/dist/qml/parse.d.ts +10 -0
- package/dist/qml/parse.d.ts.map +1 -0
- package/dist/qml/parse.js +607 -0
- package/dist/qml/parse.js.map +1 -0
- package/dist/qml/qtquick.d.ts +7 -0
- package/dist/qml/qtquick.d.ts.map +1 -0
- package/dist/qml/qtquick.js +347 -0
- package/dist/qml/qtquick.js.map +1 -0
- package/dist/qml/react.d.ts +83 -0
- package/dist/qml/react.d.ts.map +1 -0
- package/dist/qml/react.js +323 -0
- package/dist/qml/react.js.map +1 -0
- package/dist/qml/resolver.d.ts +38 -0
- package/dist/qml/resolver.d.ts.map +1 -0
- package/dist/qml/resolver.js +64 -0
- package/dist/qml/resolver.js.map +1 -0
- package/dist/qml/slots.d.ts +65 -0
- package/dist/qml/slots.d.ts.map +1 -0
- package/dist/qml/slots.js +230 -0
- package/dist/qml/slots.js.map +1 -0
- package/dist/qml/states.d.ts +5 -0
- package/dist/qml/states.d.ts.map +1 -0
- package/dist/qml/states.js +276 -0
- package/dist/qml/states.js.map +1 -0
- package/dist/qml/view-utils.d.ts +42 -0
- package/dist/qml/view-utils.d.ts.map +1 -0
- package/dist/qml/view-utils.js +121 -0
- package/dist/qml/view-utils.js.map +1 -0
- package/dist/reorder/hx.d.ts +18 -0
- package/dist/reorder/hx.d.ts.map +1 -0
- package/dist/reorder/hx.js +10 -0
- package/dist/reorder/hx.js.map +1 -0
- package/dist/reorder/index.d.ts +314 -0
- package/dist/reorder/index.d.ts.map +1 -0
- package/dist/reorder/index.js +1539 -0
- package/dist/reorder/index.js.map +1 -0
- package/dist/reorder/model.d.ts +107 -0
- package/dist/reorder/model.d.ts.map +1 -0
- package/dist/reorder/model.js +162 -0
- package/dist/reorder/model.js.map +1 -0
- package/dist/richtext/node.d.ts +15 -5
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +40 -11
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +35 -13
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +83 -27
- package/dist/richtext/runs.js.map +1 -1
- package/dist/tabs/hx.d.ts +18 -0
- package/dist/tabs/hx.d.ts.map +1 -0
- package/dist/tabs/hx.js +10 -0
- package/dist/tabs/hx.js.map +1 -0
- package/dist/tabs/index.d.ts +160 -0
- package/dist/tabs/index.d.ts.map +1 -0
- package/dist/tabs/index.js +1265 -0
- package/dist/tabs/index.js.map +1 -0
- package/dist/terminal/vt/fonts.d.ts +45 -15
- package/dist/terminal/vt/fonts.d.ts.map +1 -1
- package/dist/terminal/vt/fonts.js +89 -19
- package/dist/terminal/vt/fonts.js.map +1 -1
- package/dist/terminal/vt/index.d.ts +1 -1
- package/dist/terminal/vt/index.d.ts.map +1 -1
- package/dist/terminal/vt/index.js +3 -3
- package/dist/terminal/vt/index.js.map +1 -1
- package/dist/terminal/vt/node.d.ts +42 -0
- package/dist/terminal/vt/node.d.ts.map +1 -1
- package/dist/terminal/vt/node.js +95 -11
- package/dist/terminal/vt/node.js.map +1 -1
- package/dist/terminal/vt/pty.d.ts +16 -0
- package/dist/terminal/vt/pty.d.ts.map +1 -1
- package/dist/terminal/vt/pty.js +186 -0
- package/dist/terminal/vt/pty.js.map +1 -1
- package/dist/terminal/vt/renderer.d.ts.map +1 -1
- package/dist/terminal/vt/renderer.js +13 -3
- package/dist/terminal/vt/renderer.js.map +1 -1
- package/package.json +23 -3
- package/src/charts/components.ts +14 -7
- package/src/charts/node.ts +81 -26
- package/src/charts/render.ts +16 -6
- package/src/code-editor/node.ts +147 -53
- package/src/flow/draw.ts +104 -35
- package/src/flow/index.ts +33 -13
- package/src/flow/model.ts +4 -2
- package/src/flow/node.ts +158 -59
- package/src/flow/types.ts +46 -21
- package/src/formula/index.ts +4 -2
- package/src/formula/node.ts +24 -5
- package/src/html/controls.ts +4 -1
- package/src/html/css/cascade.ts +18 -7
- package/src/html/css/parse.ts +46 -21
- package/src/html/css/style.ts +6 -1
- package/src/html/css/values.ts +25 -9
- package/src/html/index.ts +1 -0
- package/src/html/layout/boxes.ts +19 -9
- package/src/html/layout/inline.ts +23 -1
- package/src/html/node.ts +110 -17
- package/src/html/paint.ts +17 -2
- package/src/index.ts +142 -0
- package/src/maps/clip.ts +184 -0
- package/src/maps/gzip.ts +66 -0
- package/src/maps/index.ts +316 -0
- package/src/maps/labels.ts +442 -0
- package/src/maps/mvt.ts +857 -0
- package/src/maps/node.ts +1819 -0
- package/src/maps/overlay.ts +639 -0
- package/src/maps/paint.ts +978 -0
- package/src/maps/proj.ts +641 -0
- package/src/maps/sources.ts +425 -0
- package/src/maps/style.ts +309 -0
- package/src/maps/styles.ts +1040 -0
- package/src/maps/tiles.ts +676 -0
- package/src/maps/types.ts +260 -0
- package/src/qml/containers.tsx +380 -0
- package/src/qml/controls.tsx +47 -0
- package/src/qml/globals.ts +33 -0
- package/src/qml/index.ts +67 -0
- package/src/qml/interaction.tsx +317 -0
- package/src/qml/ir.ts +80 -0
- package/src/qml/layouts.tsx +141 -0
- package/src/qml/models.ts +101 -0
- package/src/qml/objects.ts +1431 -0
- package/src/qml/parse.ts +624 -0
- package/src/qml/qtquick.tsx +413 -0
- package/src/qml/react.tsx +454 -0
- package/src/qml/resolver.ts +99 -0
- package/src/qml/slots.ts +249 -0
- package/src/qml/states.ts +318 -0
- package/src/qml/view-utils.ts +140 -0
- package/src/reorder/hx.ts +31 -0
- package/src/reorder/index.ts +2223 -0
- package/src/reorder/model.ts +232 -0
- package/src/richtext/node.ts +49 -14
- package/src/richtext/runs.ts +115 -30
- package/src/tabs/hx.ts +31 -0
- package/src/tabs/index.ts +1686 -0
- package/src/terminal/vt/fonts.ts +128 -36
- package/src/terminal/vt/index.ts +4 -2
- package/src/terminal/vt/node.ts +105 -12
- package/src/terminal/vt/pty.ts +243 -0
- package/src/terminal/vt/renderer.ts +13 -3
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { MapCanvas } from './paint.js';
|
|
2
|
+
import { GeometryBuffer } from './mvt.js';
|
|
3
|
+
import type { VectorTile } from './mvt.js';
|
|
4
|
+
import type { PreparedStyle, PreparedLayer } from './paint.js';
|
|
5
|
+
import type { TileId, Transform } from './proj.js';
|
|
6
|
+
/** ntk's font cache, structurally — the same slice `src/flow/draw.ts`
|
|
7
|
+
* names, for the same reason. */
|
|
8
|
+
export interface FontsLike {
|
|
9
|
+
layout(content: string, style: Record<string, unknown>, options?: Record<string, unknown>): {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
draw(ctx: unknown, x: number, y: number): void;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** One shaped string, kept between frames. Shaping is the expensive half of
|
|
16
|
+
* drawing text and a label does not change between frames. */
|
|
17
|
+
export interface ShapedLabel {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
layout: {
|
|
21
|
+
draw(ctx: unknown, x: number, y: number): void;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A label that could be drawn.
|
|
26
|
+
*
|
|
27
|
+
* `mx`/`my` are normalized mercator, so a candidate outlives every camera
|
|
28
|
+
* move — it is a property of the data, and collected once per tile per
|
|
29
|
+
* zoom.
|
|
30
|
+
*/
|
|
31
|
+
export interface LabelCandidate {
|
|
32
|
+
/** Stable for the life of the tile, which is what lets a placement be
|
|
33
|
+
* compared frame to frame. */
|
|
34
|
+
id: string;
|
|
35
|
+
/** `layer|text` — what the repeat-distance rule counts as "the same
|
|
36
|
+
* label". Keyed on the layer as well as the text so that a street and a
|
|
37
|
+
* place of the same name do not suppress each other. */
|
|
38
|
+
key: string;
|
|
39
|
+
text: string;
|
|
40
|
+
mx: number;
|
|
41
|
+
my: number;
|
|
42
|
+
/** Layer-wide priority; higher wins a collision. */
|
|
43
|
+
rank: number;
|
|
44
|
+
/** Logical pixels. */
|
|
45
|
+
size: number;
|
|
46
|
+
color: string;
|
|
47
|
+
halo: string | undefined;
|
|
48
|
+
haloWidth: number;
|
|
49
|
+
/** Pixels within which this text may not repeat. */
|
|
50
|
+
repeat: number;
|
|
51
|
+
}
|
|
52
|
+
/** A candidate that won its place, with the box it occupies in world
|
|
53
|
+
* pixels at the zoom it was placed for. */
|
|
54
|
+
export interface PlacedLabel extends LabelCandidate {
|
|
55
|
+
/** World pixels: `mercator × worldSize`. */
|
|
56
|
+
wx: number;
|
|
57
|
+
wy: number;
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
shaped: ShapedLabel;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The label candidates one tile contributes.
|
|
64
|
+
*
|
|
65
|
+
* Point geometry anchors at the point. Line and polygon geometry anchor at
|
|
66
|
+
* the **midpoint of the longest part** — which is not a true label
|
|
67
|
+
* placement (a street name should follow its street, and a country name
|
|
68
|
+
* should sit at the pole of inaccessibility of its border) but is the
|
|
69
|
+
* anchor those two would start from, and is right often enough to be worth
|
|
70
|
+
* having while line placement is unwritten. See `docs/prd-maps.md`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function collectLabels(tile: VectorTile, id: TileId, prepared: PreparedStyle, zoom: number, buffer: GeometryBuffer): LabelCandidate[];
|
|
73
|
+
/** Cache of shaped strings, owned by the element. */
|
|
74
|
+
export declare class LabelShaper {
|
|
75
|
+
private readonly _cache;
|
|
76
|
+
private _fonts;
|
|
77
|
+
private _family;
|
|
78
|
+
/** Device pixels per logical pixel. Text is shaped at the device size the
|
|
79
|
+
* panel wants, exactly as core shapes a `<text>` — a label on a retina
|
|
80
|
+
* screen is sharper, not bigger. */
|
|
81
|
+
private _scale;
|
|
82
|
+
constructor(fonts: FontsLike | null, family: string, scale: number);
|
|
83
|
+
/** Re-point at a new font manager, face or scale, dropping what was
|
|
84
|
+
* shaped for the old one. */
|
|
85
|
+
reconfigure(fonts: FontsLike | null, family: string, scale: number): void;
|
|
86
|
+
/** Shape one label, or null on a backend with no font manager. Widths
|
|
87
|
+
* come back in **logical** pixels, which is what placement is in. */
|
|
88
|
+
shape(text: string, size: number, color: string): ShapedLabel | null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Place candidates against each other, in world pixels.
|
|
92
|
+
*
|
|
93
|
+
* Greedy by rank, which is what every map does: sort, and take a label if
|
|
94
|
+
* nothing already taken overlaps it. The order has to be **total and
|
|
95
|
+
* stable** — rank, then the candidate's id — because a tie broken by array
|
|
96
|
+
* order would flicker as tiles arrived in a different order.
|
|
97
|
+
*/
|
|
98
|
+
export declare function placeLabels(candidates: readonly LabelCandidate[], worldSize: number, shaper: LabelShaper, options?: {
|
|
99
|
+
padding?: number;
|
|
100
|
+
}): PlacedLabel[];
|
|
101
|
+
/**
|
|
102
|
+
* Draw the placed labels that land in the pane.
|
|
103
|
+
*
|
|
104
|
+
* The halo is the same string shaped a second time in the halo colour and
|
|
105
|
+
* drawn four times around the glyphs, rather than a real outline: ntk has
|
|
106
|
+
* no glyph-outline stroke, and both runs are cached, so a label costs five
|
|
107
|
+
* composites of two shaped runs. That is cheap for the few dozen labels a
|
|
108
|
+
* pane holds and it is the difference between a place name that is
|
|
109
|
+
* readable over a motorway and one that is not.
|
|
110
|
+
*/
|
|
111
|
+
export declare function drawLabels(ctx: MapCanvas, placed: readonly PlacedLabel[], transform: Transform, pane: {
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
width: number;
|
|
115
|
+
height: number;
|
|
116
|
+
}, scale: number, clip: {
|
|
117
|
+
x: number;
|
|
118
|
+
y: number;
|
|
119
|
+
width: number;
|
|
120
|
+
height: number;
|
|
121
|
+
} | null, shaper: LabelShaper): number;
|
|
122
|
+
export type { PreparedLayer };
|
|
123
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../src/maps/labels.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { GeomType, GeometryBuffer } from './mvt.js';
|
|
2
|
+
import { resolveZoomed } from './style.js';
|
|
3
|
+
import { tileCountAt, tileKey } from './proj.js';
|
|
4
|
+
function num(value, zoom, fallback) {
|
|
5
|
+
return value === undefined ? fallback : resolveZoomed(value, zoom);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The label candidates one tile contributes.
|
|
9
|
+
*
|
|
10
|
+
* Point geometry anchors at the point. Line and polygon geometry anchor at
|
|
11
|
+
* the **midpoint of the longest part** — which is not a true label
|
|
12
|
+
* placement (a street name should follow its street, and a country name
|
|
13
|
+
* should sit at the pole of inaccessibility of its border) but is the
|
|
14
|
+
* anchor those two would start from, and is right often enough to be worth
|
|
15
|
+
* having while line placement is unwritten. See `docs/prd-maps.md`.
|
|
16
|
+
*/
|
|
17
|
+
export function collectLabels(tile, id, prepared, zoom, buffer) {
|
|
18
|
+
const out = [];
|
|
19
|
+
const n = tileCountAt(id.z);
|
|
20
|
+
const key = tileKey(id);
|
|
21
|
+
for (let i = 0; i < prepared.layers.length; i++) {
|
|
22
|
+
const { layer, filter } = prepared.layers[i];
|
|
23
|
+
if (layer.type !== 'symbol' || layer.visible === false)
|
|
24
|
+
continue;
|
|
25
|
+
if (layer.minZoom !== undefined && zoom < layer.minZoom)
|
|
26
|
+
continue;
|
|
27
|
+
if (layer.maxZoom !== undefined && zoom >= layer.maxZoom)
|
|
28
|
+
continue;
|
|
29
|
+
const source = tile.layers.get(layer.sourceLayer);
|
|
30
|
+
if (!source || source.length === 0)
|
|
31
|
+
continue;
|
|
32
|
+
const symbol = layer;
|
|
33
|
+
const size = num(symbol.textSize, zoom, 12);
|
|
34
|
+
const color = symbol.textColor
|
|
35
|
+
? resolveZoomed(symbol.textColor, zoom)
|
|
36
|
+
: '#000000';
|
|
37
|
+
const halo = symbol.textHaloColor
|
|
38
|
+
? resolveZoomed(symbol.textHaloColor, zoom)
|
|
39
|
+
: undefined;
|
|
40
|
+
const haloWidth = num(symbol.textHaloWidth, zoom, 1);
|
|
41
|
+
const rank = symbol.rank ?? 0;
|
|
42
|
+
const repeat = symbol.repeatDistance ?? 250;
|
|
43
|
+
const extent = source.extent;
|
|
44
|
+
const cursor = source.feature(0);
|
|
45
|
+
for (let f = 0; f < source.length; f++) {
|
|
46
|
+
source.seek(f, cursor);
|
|
47
|
+
if (!filter(cursor))
|
|
48
|
+
continue;
|
|
49
|
+
const raw = cursor.get(symbol.textField);
|
|
50
|
+
// The schema's fallback: a translated name field is absent for most
|
|
51
|
+
// features, and the local `name` is what a map without a translation
|
|
52
|
+
// shows rather than nothing.
|
|
53
|
+
const text = typeof raw === 'string' && raw.length > 0
|
|
54
|
+
? raw
|
|
55
|
+
: symbol.textField !== 'name'
|
|
56
|
+
? typeof cursor.get('name') === 'string'
|
|
57
|
+
? String(cursor.get('name'))
|
|
58
|
+
: ''
|
|
59
|
+
: '';
|
|
60
|
+
if (text.length === 0)
|
|
61
|
+
continue;
|
|
62
|
+
cursor.readGeometry(buffer);
|
|
63
|
+
const anchor = anchorOf(buffer, cursor.type);
|
|
64
|
+
if (!anchor)
|
|
65
|
+
continue;
|
|
66
|
+
out.push({
|
|
67
|
+
id: `${key}:${layer.id}:${f}`,
|
|
68
|
+
key: `${layer.id}|${text}`,
|
|
69
|
+
text,
|
|
70
|
+
// Tile-local to normalized mercator, the same arithmetic the
|
|
71
|
+
// rasterizer's transform does and for the same precision reason.
|
|
72
|
+
mx: (id.x + anchor.x / extent) / n,
|
|
73
|
+
my: (id.y + anchor.y / extent) / n,
|
|
74
|
+
rank,
|
|
75
|
+
size,
|
|
76
|
+
color,
|
|
77
|
+
halo,
|
|
78
|
+
haloWidth,
|
|
79
|
+
repeat,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
function anchorOf(buffer, type) {
|
|
86
|
+
if (buffer.points === 0)
|
|
87
|
+
return null;
|
|
88
|
+
if (type === GeomType.Point) {
|
|
89
|
+
return { x: buffer.coords[0], y: buffer.coords[1] };
|
|
90
|
+
}
|
|
91
|
+
// The longest part, by its box — a cheap stand-in for arc length that
|
|
92
|
+
// does not need a second pass over the vertices.
|
|
93
|
+
let best = 0;
|
|
94
|
+
let bestSpan = -1;
|
|
95
|
+
for (let part = 0; part < buffer.parts; part++) {
|
|
96
|
+
const at = part * 4;
|
|
97
|
+
const span = buffer.partBounds[at + 2] -
|
|
98
|
+
buffer.partBounds[at] +
|
|
99
|
+
(buffer.partBounds[at + 3] - buffer.partBounds[at + 1]);
|
|
100
|
+
if (span > bestSpan) {
|
|
101
|
+
bestSpan = span;
|
|
102
|
+
best = part;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const from = buffer.starts[best];
|
|
106
|
+
const to = buffer.starts[best + 1];
|
|
107
|
+
if (to <= from)
|
|
108
|
+
return null;
|
|
109
|
+
const mid = from + ((to - from) >> 1);
|
|
110
|
+
return { x: buffer.coords[mid * 2], y: buffer.coords[mid * 2 + 1] };
|
|
111
|
+
}
|
|
112
|
+
/** Cache of shaped strings, owned by the element. */
|
|
113
|
+
export class LabelShaper {
|
|
114
|
+
_cache = new Map();
|
|
115
|
+
_fonts;
|
|
116
|
+
_family;
|
|
117
|
+
/** Device pixels per logical pixel. Text is shaped at the device size the
|
|
118
|
+
* panel wants, exactly as core shapes a `<text>` — a label on a retina
|
|
119
|
+
* screen is sharper, not bigger. */
|
|
120
|
+
_scale;
|
|
121
|
+
constructor(fonts, family, scale) {
|
|
122
|
+
this._fonts = fonts;
|
|
123
|
+
this._family = family;
|
|
124
|
+
this._scale = scale;
|
|
125
|
+
}
|
|
126
|
+
/** Re-point at a new font manager, face or scale, dropping what was
|
|
127
|
+
* shaped for the old one. */
|
|
128
|
+
reconfigure(fonts, family, scale) {
|
|
129
|
+
if (this._fonts === fonts &&
|
|
130
|
+
this._family === family &&
|
|
131
|
+
this._scale === scale) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this._fonts = fonts;
|
|
135
|
+
this._family = family;
|
|
136
|
+
this._scale = scale;
|
|
137
|
+
this._cache.clear();
|
|
138
|
+
}
|
|
139
|
+
/** Shape one label, or null on a backend with no font manager. Widths
|
|
140
|
+
* come back in **logical** pixels, which is what placement is in. */
|
|
141
|
+
shape(text, size, color) {
|
|
142
|
+
const fonts = this._fonts;
|
|
143
|
+
if (!fonts)
|
|
144
|
+
return null;
|
|
145
|
+
const key = `${this._family}|${size}|${color}|${text}`;
|
|
146
|
+
const hit = this._cache.get(key);
|
|
147
|
+
if (hit)
|
|
148
|
+
return hit;
|
|
149
|
+
// Bounded, so a map panned across a continent cannot turn the cache
|
|
150
|
+
// into a leak. Cleared wholesale rather than evicted one at a time: the
|
|
151
|
+
// labels on screen are re-shaped on the next frame and the cost of that
|
|
152
|
+
// is a few hundred strings once.
|
|
153
|
+
if (this._cache.size > 4000)
|
|
154
|
+
this._cache.clear();
|
|
155
|
+
const layout = fonts.layout(text, {
|
|
156
|
+
family: this._family,
|
|
157
|
+
size: size * this._scale,
|
|
158
|
+
weight: 400,
|
|
159
|
+
style: 'normal',
|
|
160
|
+
color,
|
|
161
|
+
});
|
|
162
|
+
const shaped = {
|
|
163
|
+
width: layout.width / this._scale,
|
|
164
|
+
height: layout.height / this._scale,
|
|
165
|
+
layout,
|
|
166
|
+
};
|
|
167
|
+
this._cache.set(key, shaped);
|
|
168
|
+
return shaped;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Place candidates against each other, in world pixels.
|
|
173
|
+
*
|
|
174
|
+
* Greedy by rank, which is what every map does: sort, and take a label if
|
|
175
|
+
* nothing already taken overlaps it. The order has to be **total and
|
|
176
|
+
* stable** — rank, then the candidate's id — because a tie broken by array
|
|
177
|
+
* order would flicker as tiles arrived in a different order.
|
|
178
|
+
*/
|
|
179
|
+
export function placeLabels(candidates, worldSize, shaper, options) {
|
|
180
|
+
const padding = options?.padding ?? 2;
|
|
181
|
+
const sorted = [...candidates].sort((a, b) => b.rank - a.rank || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
182
|
+
const placed = [];
|
|
183
|
+
// A sparse grid over world pixels. The cell is sized for the labels
|
|
184
|
+
// themselves, so a box touches one or two cells and a collision test is a
|
|
185
|
+
// handful of comparisons rather than a scan of everything placed.
|
|
186
|
+
const CELL = 64;
|
|
187
|
+
const grid = new Map();
|
|
188
|
+
const cellKey = (cx, cy) => cx * 0x40000 + cy;
|
|
189
|
+
/** Where each distinct text has already been placed, for the
|
|
190
|
+
* repeat-distance rule. */
|
|
191
|
+
const byText = new Map();
|
|
192
|
+
for (const candidate of sorted) {
|
|
193
|
+
const shaped = shaper.shape(candidate.text, candidate.size, candidate.color);
|
|
194
|
+
if (!shaped)
|
|
195
|
+
return placed; // no font manager: nothing can be measured
|
|
196
|
+
const wx = candidate.mx * worldSize;
|
|
197
|
+
const wy = candidate.my * worldSize;
|
|
198
|
+
// The repeat test before the overlap test, because it is the cheaper
|
|
199
|
+
// one and because it is what rejects most of a street layer: a street
|
|
200
|
+
// is one feature per segment, so the same name arrives a dozen times
|
|
201
|
+
// strung out along the road, none of them overlapping any other.
|
|
202
|
+
if (candidate.repeat > 0) {
|
|
203
|
+
const already = byText.get(candidate.key);
|
|
204
|
+
if (already) {
|
|
205
|
+
const limit = candidate.repeat * candidate.repeat;
|
|
206
|
+
let tooClose = false;
|
|
207
|
+
for (const at of already) {
|
|
208
|
+
const dx = at.wx - wx;
|
|
209
|
+
const dy = at.wy - wy;
|
|
210
|
+
if (dx * dx + dy * dy < limit) {
|
|
211
|
+
tooClose = true;
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (tooClose)
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const width = shaped.width + padding * 2;
|
|
220
|
+
const height = shaped.height + padding * 2;
|
|
221
|
+
const left = wx - width / 2;
|
|
222
|
+
const top = wy - height / 2;
|
|
223
|
+
const x0 = Math.floor(left / CELL);
|
|
224
|
+
const x1 = Math.floor((left + width) / CELL);
|
|
225
|
+
const y0 = Math.floor(top / CELL);
|
|
226
|
+
const y1 = Math.floor((top + height) / CELL);
|
|
227
|
+
let free = true;
|
|
228
|
+
for (let cx = x0; cx <= x1 && free; cx++) {
|
|
229
|
+
for (let cy = y0; cy <= y1 && free; cy++) {
|
|
230
|
+
const bucket = grid.get(cellKey(cx, cy));
|
|
231
|
+
if (!bucket)
|
|
232
|
+
continue;
|
|
233
|
+
for (const other of bucket) {
|
|
234
|
+
if (left < other.wx - other.width / 2 + other.width &&
|
|
235
|
+
left + width > other.wx - other.width / 2 &&
|
|
236
|
+
top < other.wy - other.height / 2 + other.height &&
|
|
237
|
+
top + height > other.wy - other.height / 2) {
|
|
238
|
+
free = false;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (!free)
|
|
245
|
+
continue;
|
|
246
|
+
const entry = {
|
|
247
|
+
...candidate,
|
|
248
|
+
wx,
|
|
249
|
+
wy,
|
|
250
|
+
width,
|
|
251
|
+
height,
|
|
252
|
+
shaped,
|
|
253
|
+
};
|
|
254
|
+
placed.push(entry);
|
|
255
|
+
if (candidate.repeat > 0) {
|
|
256
|
+
const already = byText.get(candidate.key);
|
|
257
|
+
if (already)
|
|
258
|
+
already.push({ wx, wy });
|
|
259
|
+
else
|
|
260
|
+
byText.set(candidate.key, [{ wx, wy }]);
|
|
261
|
+
}
|
|
262
|
+
for (let cx = x0; cx <= x1; cx++) {
|
|
263
|
+
for (let cy = y0; cy <= y1; cy++) {
|
|
264
|
+
const at = cellKey(cx, cy);
|
|
265
|
+
const bucket = grid.get(at);
|
|
266
|
+
if (bucket)
|
|
267
|
+
bucket.push(entry);
|
|
268
|
+
else
|
|
269
|
+
grid.set(at, [entry]);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return placed;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Draw the placed labels that land in the pane.
|
|
277
|
+
*
|
|
278
|
+
* The halo is the same string shaped a second time in the halo colour and
|
|
279
|
+
* drawn four times around the glyphs, rather than a real outline: ntk has
|
|
280
|
+
* no glyph-outline stroke, and both runs are cached, so a label costs five
|
|
281
|
+
* composites of two shaped runs. That is cheap for the few dozen labels a
|
|
282
|
+
* pane holds and it is the difference between a place name that is
|
|
283
|
+
* readable over a motorway and one that is not.
|
|
284
|
+
*/
|
|
285
|
+
export function drawLabels(ctx, placed, transform, pane, scale, clip, shaper) {
|
|
286
|
+
let drawn = 0;
|
|
287
|
+
const world = transform.world;
|
|
288
|
+
const originX = pane.x + transform.paneX - transform.centerX * world;
|
|
289
|
+
const originY = pane.y + transform.paneY - transform.centerY * world;
|
|
290
|
+
for (const label of placed) {
|
|
291
|
+
const x = originX + label.wx - label.shaped.width / 2;
|
|
292
|
+
const y = originY + label.wy - label.shaped.height / 2;
|
|
293
|
+
if (x + label.shaped.width < pane.x ||
|
|
294
|
+
y + label.shaped.height < pane.y ||
|
|
295
|
+
x > pane.x + pane.width ||
|
|
296
|
+
y > pane.y + pane.height) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (clip &&
|
|
300
|
+
(x + label.shaped.width < clip.x ||
|
|
301
|
+
y + label.shaped.height < clip.y ||
|
|
302
|
+
x > clip.x + clip.width ||
|
|
303
|
+
y > clip.y + clip.height)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
const dx = Math.round(x * scale);
|
|
307
|
+
const dy = Math.round(y * scale);
|
|
308
|
+
if (label.halo !== undefined && label.haloWidth > 0) {
|
|
309
|
+
const halo = shaper.shape(label.text, label.size, label.halo);
|
|
310
|
+
if (halo) {
|
|
311
|
+
const offset = Math.max(1, Math.round(label.haloWidth * scale));
|
|
312
|
+
halo.layout.draw(ctx, dx - offset, dy);
|
|
313
|
+
halo.layout.draw(ctx, dx + offset, dy);
|
|
314
|
+
halo.layout.draw(ctx, dx, dy - offset);
|
|
315
|
+
halo.layout.draw(ctx, dx, dy + offset);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
label.shaped.layout.draw(ctx, dx, dy);
|
|
319
|
+
drawn++;
|
|
320
|
+
}
|
|
321
|
+
return drawn;
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","sourceRoot":"","sources":["../../src/maps/labels.ts"],"names":[],"mappings":"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"}
|