@tangram.gl/basemap-layers 0.0.0-stage → 0.0.1

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 (105) hide show
  1. package/README.md +34 -2
  2. package/THIRD-PARTY-NOTICES.md +205 -0
  3. package/dist/geojson-worker.js +2160 -0
  4. package/dist/geojson-worker.js.map +6 -0
  5. package/dist/index.cjs +11388 -0
  6. package/dist/index.cjs.map +6 -0
  7. package/dist/index.js +11369 -0
  8. package/dist/index.js.map +6 -0
  9. package/dist/map-style.cjs +445 -0
  10. package/dist/map-style.cjs.map +6 -0
  11. package/dist/map-style.js +431 -0
  12. package/dist/map-style.js.map +6 -0
  13. package/dist/types/arabic-shaping.d.ts +7 -0
  14. package/dist/types/atmosphere-layer.d.ts +10 -0
  15. package/dist/types/basemap-layer.d.ts +150 -0
  16. package/dist/types/bidi.d.ts +8 -0
  17. package/dist/types/circle-layer.d.ts +49 -0
  18. package/dist/types/fill-extrusion-lighting-extension.d.ts +49 -0
  19. package/dist/types/fill-outline-extension.d.ts +22 -0
  20. package/dist/types/fill-pattern.d.ts +99 -0
  21. package/dist/types/fill-style-extensions.d.ts +100 -0
  22. package/dist/types/geojson-source.d.ts +29 -0
  23. package/dist/types/geojson-tiler.d.ts +48 -0
  24. package/dist/types/geojson-worker.d.ts +40 -0
  25. package/dist/types/globe-horizon-extension.d.ts +61 -0
  26. package/dist/types/globe-layers.d.ts +239 -0
  27. package/dist/types/globe-line-angle-extension.d.ts +37 -0
  28. package/dist/types/glyph-font-renderer.d.ts +37 -0
  29. package/dist/types/glyph-pbf.d.ts +37 -0
  30. package/dist/types/glyph-store.d.ts +103 -0
  31. package/dist/types/grid-index.d.ts +47 -0
  32. package/dist/types/hillshade-layer.d.ts +154 -0
  33. package/dist/types/index.d.ts +9 -0
  34. package/dist/types/is-globe-viewport.d.ts +2 -0
  35. package/dist/types/label-font-renderer.d.ts +18 -0
  36. package/dist/types/label-placement.d.ts +247 -0
  37. package/dist/types/label-text-layer.d.ts +231 -0
  38. package/dist/types/line-blur-extension.d.ts +73 -0
  39. package/dist/types/line-glyphs.d.ts +60 -0
  40. package/dist/types/line-placement.d.ts +93 -0
  41. package/dist/types/map-style-loader.d.ts +48 -0
  42. package/dist/types/map-style-schema.d.ts +72 -0
  43. package/dist/types/map-style.d.ts +6 -0
  44. package/dist/types/mapbox-style.d.ts +40 -0
  45. package/dist/types/mvt-label-layer.d.ts +923 -0
  46. package/dist/types/polylabel.d.ts +17 -0
  47. package/dist/types/raster-color-extension.d.ts +146 -0
  48. package/dist/types/shared-texture.d.ts +34 -0
  49. package/dist/types/sort-key.d.ts +10 -0
  50. package/dist/types/sprite.d.ts +82 -0
  51. package/dist/types/style-accessor.d.ts +45 -0
  52. package/dist/types/style-expression.d.ts +83 -0
  53. package/dist/types/style-resolver.d.ts +94 -0
  54. package/dist/types/text-font.d.ts +36 -0
  55. package/dist/types/text-halo-blur-extension.d.ts +55 -0
  56. package/dist/types/text-layout.d.ts +71 -0
  57. package/dist/types/util.d.ts +22 -0
  58. package/dist/types/zoom-paint-extension.d.ts +72 -0
  59. package/package.json +80 -3
  60. package/src/arabic-shaping.ts +366 -0
  61. package/src/atmosphere-layer.ts +19 -0
  62. package/src/basemap-layer.ts +533 -0
  63. package/src/bidi.ts +199 -0
  64. package/src/circle-layer.ts +191 -0
  65. package/src/fill-extrusion-lighting-extension.ts +206 -0
  66. package/src/fill-outline-extension.ts +70 -0
  67. package/src/fill-pattern.ts +400 -0
  68. package/src/fill-style-extensions.ts +177 -0
  69. package/src/geojson-source.ts +318 -0
  70. package/src/geojson-tiler.ts +185 -0
  71. package/src/geojson-worker.ts +98 -0
  72. package/src/globe-horizon-extension.ts +64 -0
  73. package/src/globe-layers.ts +3487 -0
  74. package/src/globe-line-angle-extension.ts +131 -0
  75. package/src/glyph-font-renderer.ts +173 -0
  76. package/src/glyph-pbf.ts +164 -0
  77. package/src/glyph-store.ts +326 -0
  78. package/src/grid-index.ts +177 -0
  79. package/src/hillshade-layer.ts +775 -0
  80. package/src/index.ts +18 -0
  81. package/src/is-globe-viewport.ts +24 -0
  82. package/src/label-font-renderer.ts +159 -0
  83. package/src/label-placement.ts +727 -0
  84. package/src/label-text-layer.ts +913 -0
  85. package/src/line-blur-extension.ts +237 -0
  86. package/src/line-glyphs.ts +364 -0
  87. package/src/line-placement.ts +446 -0
  88. package/src/map-style-loader.ts +56 -0
  89. package/src/map-style-schema.ts +83 -0
  90. package/src/map-style.ts +23 -0
  91. package/src/mapbox-style.ts +168 -0
  92. package/src/mvt-label-layer.ts +3744 -0
  93. package/src/polylabel.ts +312 -0
  94. package/src/raster-color-extension.ts +245 -0
  95. package/src/shared-texture.ts +153 -0
  96. package/src/sort-key.ts +63 -0
  97. package/src/sprite.ts +244 -0
  98. package/src/style-accessor.ts +95 -0
  99. package/src/style-expression.ts +327 -0
  100. package/src/style-resolver.ts +301 -0
  101. package/src/text-font.ts +150 -0
  102. package/src/text-halo-blur-extension.ts +115 -0
  103. package/src/text-layout.ts +441 -0
  104. package/src/util.ts +47 -0
  105. package/src/zoom-paint-extension.ts +207 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Whether `text-letter-spacing` applies to `text`: as in MapLibre, text with any character of a
3
+ * cursive script (Arabic, Duployan, Mongolian, Old Uyghur, Syriac) is not letter-spaced.
4
+ */
5
+ export declare function allowsLetterSpacing(text: string): boolean;
6
+ /**
7
+ * `text-transform`, as MapLibre applies it: locale-aware upper or lower case, then Arabic shaping
8
+ * (see {@link applyArabicShaping}), so that the glyphs looked up, measured and drawn are those of
9
+ * the shapes the letters take.
10
+ */
11
+ export declare function transformText(text: string, transform: unknown): string;
12
+ /**
13
+ * Longest label, in UTF-16 code units, that {@link wrapText} wraps. Line breaking is quadratic in
14
+ * the number of break opportunities, and tile data is untrusted, so longer text is returned
15
+ * unwrapped. Real labels are far shorter; at this length even ideographic text, where every
16
+ * character is a break opportunity, costs tens of thousands of steps.
17
+ */
18
+ export declare const MAX_WRAPPED_TEXT_LENGTH = 256;
19
+ /**
20
+ * Line-breaking work that {@link wrapText} may still spend, shared by the labels of one tile and
21
+ * style layer. Each wrap costs an upper bound of its steps: one per character plus one per pair of
22
+ * break opportunities. A label whose cost exceeds what is left is returned unwrapped.
23
+ */
24
+ export type WrapBudget = {
25
+ steps: number;
26
+ };
27
+ /**
28
+ * Breaks `text` into lines no wider than `maxWidth` ems where it can, with MapLibre's balanced
29
+ * line breaking, and returns the lines joined by '\n', each in the order it is drawn (see
30
+ * {@link orderBidirectionalText}). Advances from `measure` are in ems; words without break
31
+ * opportunities stay intact, even when they exceed the requested width. Text longer than
32
+ * {@link MAX_WRAPPED_TEXT_LENGTH}, or whose cost exceeds `budget`, is not broken.
33
+ */
34
+ export declare function wrapText(text: string, maxWidth: number, measure: (character: string) => number, budget?: WrapBudget): string;
35
+ /**
36
+ * Puts text that is not wrapped, such as a label along a line, into the order it is drawn: right-
37
+ * to-left runs reversed, as MapLibre does. Text without right-to-left characters is unchanged.
38
+ */
39
+ export declare function orderBidirectionalText(text: string): string;
40
+ /**
41
+ * Whether text can be measured with a canvas here; otherwise {@link getCharacterWidthMeasurer}
42
+ * returns {@link FALLBACK_CHARACTER_WIDTH} for every character.
43
+ */
44
+ export declare function canMeasureText(): boolean;
45
+ /** Advance in ems used when canvas measurement is unavailable, as for missing atlas glyphs. */
46
+ export declare const FALLBACK_CHARACTER_WIDTH = 0.5;
47
+ /**
48
+ * Bounds on the measurement caches: fonts and characters both come from untrusted style and tile
49
+ * data. A full cache is cleared rather than grown.
50
+ */
51
+ export declare const MAX_CACHED_FONTS = 32;
52
+ export declare const MAX_CACHED_CHARACTERS = 4096;
53
+ /**
54
+ * Forgets the character advances measured for a CSS font, so they are measured again: a font that
55
+ * was still loading was measured with a fallback font. When the advances measured before differ
56
+ * from those measured now, or were not all kept, the font's revision changes.
57
+ */
58
+ export declare function forgetCharacterWidths(fontWeight: number | string, fontFamily: string): void;
59
+ /**
60
+ * A number that changes whenever {@link forgetCharacterWidths} finds a font's advances changed, so
61
+ * that what was measured in it before can be measured again. Loading another font, or a measurer
62
+ * evicted from a full cache, measuring the same advances again, does not change it.
63
+ */
64
+ export declare function getCharacterWidthsRevision(fontWeight: number | string, fontFamily: string): number;
65
+ /**
66
+ * Returns a function giving a character's advance width in ems for a CSS font, measured the way
67
+ * deck.gl's TextLayer builds its font atlas: at 64px, then divided by 64. Measurers and character
68
+ * advances are cached, up to {@link MAX_CACHED_FONTS} and {@link MAX_CACHED_CHARACTERS}.
69
+ * Environments without a canvas 2D context use a half-em advance.
70
+ */
71
+ export declare function getCharacterWidthMeasurer(fontWeight: number | string, fontFamily: string): (character: string) => number;
@@ -0,0 +1,22 @@
1
+ type FeatureLike = {
2
+ properties?: Record<string, unknown>;
3
+ };
4
+ /**
5
+ * Options for {@link featuresArrayToObject}.
6
+ */
7
+ export type FeaturesArrayToObjectOptions = {
8
+ /** Features to group by the requested layer-name property. */
9
+ features?: FeatureLike[];
10
+ /** Feature property name that contains the source-layer identifier. */
11
+ layerName?: string;
12
+ /** Optional source name wrapper for the returned object. */
13
+ sourceName?: string | null;
14
+ };
15
+ /**
16
+ * Converts an array of GeoJSON-like features into an object keyed by layer
17
+ * name, optionally wrapped by a source identifier.
18
+ */
19
+ export declare function featuresArrayToObject(options?: FeaturesArrayToObjectOptions): Record<string, FeatureLike[] | Record<string, FeatureLike[]>>;
20
+ /** Whether two lists hold the same items, by identity. */
21
+ export declare function isSameList(a: readonly unknown[] | undefined, b: readonly unknown[]): boolean;
22
+ export {};
@@ -0,0 +1,72 @@
1
+ import { LayerExtension } from '@deck.gl/core';
2
+ import type { Accessor, Layer, LayerContext } from '@deck.gl/core';
3
+ import type { Device, Texture } from '@luma.gl/core';
4
+ /** The most style layers whose paint one layer can take from `ZoomPaintExtension`. */
5
+ export declare const MAX_ZOOM_PAINT_PARTS = 64;
6
+ /** The rows of `ZoomPaintValues`. */
7
+ export declare const ZOOM_PAINT_WIDTH_ROW = 0;
8
+ export declare const ZOOM_PAINT_LINE_COLOR_ROW = 1;
9
+ export declare const ZOOM_PAINT_FILL_COLOR_ROW = 2;
10
+ /**
11
+ * The paint of each style layer drawn by a layer, at one zoom: an RGBA texel per style layer
12
+ * (column) and value (row), `MAX_ZOOM_PAINT_PARTS` by 3. Column `i` is the style layer that
13
+ * `getStylePart` returns `i` for.
14
+ *
15
+ * - `ZOOM_PAINT_WIDTH_ROW`: in red, a factor of the layer's width attribute.
16
+ * - `ZOOM_PAINT_LINE_COLOR_ROW`, `ZOOM_PAINT_FILL_COLOR_ROW`: a color in 0-1, which replaces the
17
+ * layer's color attribute unless its alpha is negative: the attribute then holds the style
18
+ * layer's per-feature colors.
19
+ */
20
+ export type ZoomPaintValues = Float32Array;
21
+ /** Creates values with every width factor 1 and every color taken from the attributes. */
22
+ export declare function createZoomPaintValues(): ZoomPaintValues;
23
+ /** The index of a style layer's texel in a row of `ZoomPaintValues`. */
24
+ export declare function getZoomPaintOffset(row: number, part: number): number;
25
+ /**
26
+ * The paint of the style layers drawn by a layer, and the texture that hands it to the shaders,
27
+ * which `destroy` releases.
28
+ */
29
+ export declare class ZoomPaint {
30
+ readonly getValues: () => ZoomPaintValues;
31
+ private texture;
32
+ private written;
33
+ /** `getValues` returns the values at the current zoom, the same array while they are unchanged. */
34
+ constructor(getValues: () => ZoomPaintValues);
35
+ /** The texture of the current values, created on first use. */
36
+ getTexture(device: Device): Texture;
37
+ destroy(): void;
38
+ }
39
+ export type ZoomPaintExtensionProps = {
40
+ /** The paint to apply; the layer draws its attributes as they are without it. */
41
+ zoomPaint?: ZoomPaint | null;
42
+ /** Which of `zoomPaint`'s style layers each object belongs to. */
43
+ getStylePart?: Accessor<any, number>;
44
+ };
45
+ /**
46
+ * Takes the zoom-dependent paint of the style layers a `PathLayer` or flat `SolidPolygonLayer`
47
+ * draws from a texture instead of attributes: per style layer, its line width and, when they are
48
+ * the same for all of its features, its colors. The values are read when the layer draws, so a
49
+ * zoom step changes a small texture, shared by every layer with the same `zoomPaint`: the layers'
50
+ * props, and so their attributes, stay the same. Each object's style layer is an attribute, which
51
+ * changes only with the data.
52
+ *
53
+ * The width factor applies after `widthMinPixels` and `widthMaxPixels`, which must not clamp.
54
+ * The owner of a `ZoomPaint` destroys its texture. WebGL only.
55
+ */
56
+ export declare class ZoomPaintExtension extends LayerExtension {
57
+ static extensionName: string;
58
+ static defaultProps: {
59
+ zoomPaint: {
60
+ type: string;
61
+ value: null;
62
+ };
63
+ getStylePart: {
64
+ type: string;
65
+ value: number;
66
+ };
67
+ };
68
+ isEnabled(layer: Layer): boolean;
69
+ getShaders(this: Layer<ZoomPaintExtensionProps>, extension: this): any;
70
+ initializeState(this: Layer<ZoomPaintExtensionProps>, context: LayerContext, extension: this): void;
71
+ draw(this: Layer<ZoomPaintExtensionProps>, params: any, extension: this): void;
72
+ }
package/package.json CHANGED
@@ -1,6 +1,83 @@
1
1
  {
2
2
  "name": "@tangram.gl/basemap-layers",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.1",
4
+ "description": "Basemap layer and map-style helpers for deck.gl.",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "deck.gl",
8
+ "mapbox",
9
+ "basemap"
10
+ ],
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/visgl/tangram.gl.git",
14
+ "directory": "modules/basemap-layers"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "types": "./dist/types/index.d.ts",
22
+ "main": "./dist/index.cjs",
23
+ "module": "./dist/index.js",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/types/index.d.ts",
27
+ "require": "./dist/index.cjs",
28
+ "import": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./map-style": {
32
+ "types": "./dist/types/map-style.d.ts",
33
+ "require": "./dist/map-style.cjs",
34
+ "import": "./dist/map-style.js",
35
+ "default": "./dist/map-style.js"
36
+ }
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "src",
41
+ "THIRD-PARTY-NOTICES.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "yarn build:types && yarn build:bundle && yarn build:worker",
45
+ "build:types": "node ../../scripts/build-package-types.mjs modules/basemap-layers index.ts map-style.ts",
46
+ "build:bundle": "ocular-bundle src/index.ts --env=dev --format=esm --output=dist/index.js --externals=@loaders.gl/loader-utils,@loaders.gl/mvt,@mapbox/tiny-sdf,@maplibre/geojson-vt,@maplibre/maplibre-gl-style-spec,@turf/polygon-to-line,bidi-js,zod --sourcemap=true --sourcesContent=false && ocular-bundle src/map-style.ts --env=dev --format=esm --output=dist/map-style.js --externals=@loaders.gl/loader-utils,@loaders.gl/mvt,@mapbox/tiny-sdf,@maplibre/geojson-vt,@maplibre/maplibre-gl-style-spec,@turf/polygon-to-line,bidi-js,zod --sourcemap=true --sourcesContent=false && ocular-bundle src/index.ts --env=dev --format=cjs --output=dist/index.cjs --externals=@loaders.gl/loader-utils,@loaders.gl/mvt,@mapbox/tiny-sdf,@maplibre/geojson-vt,@maplibre/maplibre-gl-style-spec,@turf/polygon-to-line,bidi-js,zod --sourcemap=true --sourcesContent=false && ocular-bundle src/map-style.ts --env=dev --format=cjs --output=dist/map-style.cjs --externals=@loaders.gl/loader-utils,@loaders.gl/mvt,@mapbox/tiny-sdf,@maplibre/geojson-vt,@maplibre/maplibre-gl-style-spec,@turf/polygon-to-line,bidi-js,zod --sourcemap=true --sourcesContent=false",
47
+ "build:worker": "ocular-bundle src/geojson-worker.ts --env=dev --format=iife --output=dist/geojson-worker.js --sourcemap=true --sourcesContent=false",
48
+ "prepack": "yarn build",
49
+ "test": "yarn --cwd ../.. vitest run --config modules/basemap-layers/vitest.config.ts",
50
+ "test-watch": "yarn --cwd ../.. vitest --config modules/basemap-layers/vitest.config.ts"
51
+ },
52
+ "devDependencies": {
53
+ "@deck.gl-community/geo-layers": "~9.4.2",
54
+ "@deck.gl/test-utils": "~9.4.0",
55
+ "@fontsource/montserrat": "5.3.0",
56
+ "@fontsource/noto-sans": "5.3.0",
57
+ "@fontsource/open-sans": "5.3.0",
58
+ "@loaders.gl/core": "^4.5.1",
59
+ "@vis.gl/dev-tools": "2.0.0-alpha.8",
60
+ "maplibre-gl": "6.13.0",
61
+ "vitest": "^4.0.18"
62
+ },
63
+ "dependencies": {
64
+ "@loaders.gl/loader-utils": "^4.5.1",
65
+ "@loaders.gl/mvt": "^4.5.1",
66
+ "@mapbox/tiny-sdf": "^2.0.5",
67
+ "@maplibre/geojson-vt": "^6.1.2",
68
+ "@maplibre/maplibre-gl-style-spec": "^24.8.1",
69
+ "@turf/polygon-to-line": "^6.0.3",
70
+ "bidi-js": "^1.1.0",
71
+ "zod": "^4.0.0"
72
+ },
73
+ "peerDependencies": {
74
+ "@deck.gl-community/geo-layers": "~9.4.2",
75
+ "@deck.gl/core": "~9.4.0",
76
+ "@deck.gl/extensions": "~9.4.0",
77
+ "@deck.gl/geo-layers": "~9.4.0",
78
+ "@deck.gl/layers": "~9.4.0",
79
+ "@loaders.gl/core": "^4.5.1",
80
+ "@luma.gl/core": "~9.4.0",
81
+ "@luma.gl/engine": "~9.4.0"
82
+ }
6
83
  }
@@ -0,0 +1,366 @@
1
+ // tangram-layers
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ // deck.gl-community
6
+ // SPDX-License-Identifier: MIT AND BSD-3-Clause AND Unicode-3.0
7
+ // Copyright (c) vis.gl contributors
8
+ // Copyright (c) 2023, MapLibre contributors
9
+
10
+ /**
11
+ * @license
12
+ * Portions of this file are adapted from MapLibre GL JS v6.13.0, src/symbol/arabic_shaping.ts and the
13
+ * tables its build/generate-unicode-data.ts writes to src/util/unicode_properties.g.ts,
14
+ * under this license:
15
+ *
16
+ * Copyright (c) 2023, MapLibre contributors
17
+ *
18
+ * All rights reserved.
19
+ *
20
+ * Redistribution and use in source and binary forms, with or without modification,
21
+ * are permitted provided that the following conditions are met:
22
+ *
23
+ * * Redistributions of source code must retain the above copyright notice,
24
+ * this list of conditions and the following disclaimer.
25
+ * * Redistributions in binary form must reproduce the above copyright notice,
26
+ * this list of conditions and the following disclaimer in the documentation
27
+ * and/or other materials provided with the distribution.
28
+ * * Neither the name of MapLibre GL JS nor the names of its contributors
29
+ * may be used to endorse or promote products derived from this software
30
+ * without specific prior written permission.
31
+ *
32
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
36
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ */
44
+
45
+ /**
46
+ * @license
47
+ * The joining types, presentation forms and ligatures below are derived from the Unicode
48
+ * Character Database 17.0.0 (extracted/DerivedJoiningType.txt and UnicodeData.txt), under
49
+ * this license:
50
+ *
51
+ * UNICODE LICENSE V3
52
+ *
53
+ * COPYRIGHT AND PERMISSION NOTICE
54
+ *
55
+ * Copyright © 1991-2026 Unicode, Inc.
56
+ *
57
+ * NOTICE TO USER: Carefully read the following legal agreement. BY
58
+ * DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
59
+ * SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
60
+ * TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
61
+ * DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
62
+ *
63
+ * Permission is hereby granted, free of charge, to any person obtaining a
64
+ * copy of data files and any associated documentation (the "Data Files") or
65
+ * software and any associated documentation (the "Software") to deal in the
66
+ * Data Files or Software without restriction, including without limitation
67
+ * the rights to use, copy, modify, merge, publish, distribute, and/or sell
68
+ * copies of the Data Files or Software, and to permit persons to whom the
69
+ * Data Files or Software are furnished to do so, provided that either (a)
70
+ * this copyright and permission notice appear with all copies of the Data
71
+ * Files or Software, or (b) this copyright and permission notice appear in
72
+ * associated Documentation.
73
+ *
74
+ * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
75
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
76
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
77
+ * THIRD PARTY RIGHTS.
78
+ *
79
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
80
+ * BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
81
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
82
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
83
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
84
+ * FILES OR SOFTWARE.
85
+ *
86
+ * Except as contained in this notice, the name of a copyright holder shall
87
+ * not be used in advertising or otherwise to promote the sale, use or other
88
+ * dealings in these Data Files or Software without prior written
89
+ * authorization of the copyright holder.
90
+ */
91
+
92
+ // Arabic shaping as MapLibre GL JS 6.13 does it, without a right-to-left text plugin.
93
+
94
+ // The joining type of each code point, as delta-encoded base-36 `start,length` ranges per type.
95
+ const ENCODED_JOINING_TYPES: Record<string, string> = {
96
+ C: '18g,1;g2,3;4nb,1',
97
+ D: '17k,1;5,1;1,1;1,5;4,d;1,7;1,2;z,2;8,g;i,12;1,2;9,1;1,1;1,2;14,3;2,1;28,9;3,f;2,4;1,1;2,3;2,6;7a,1;2,5;1,1;g,a;5,2;2,6;1,f',
98
+ R: '17m,4;1,1;1,1;5,4;l,1;14,3;1,3;g,i;12,1;2,9;1,1;1,1;2,2;1,1;o,2;2x,3;f,2;4,1;1,2;3,2;6u,j;b,1;r,3;1,1;2,2;6,1',
99
+ T: '174,b;1,1;1a,l;g,1;2t,7;2,6;2,2;1,4;bt,9;16,o;1,t;1clb,1'
100
+ };
101
+
102
+ /**
103
+ * Each Arabic letter's Presentation Forms code points, as `[isolated, final, initial, medial]`.
104
+ * A shape the letter is not written in is 0.
105
+ */
106
+ const PRESENTATION_FORMS: Record<number, [number, number, number, number]> = {
107
+ 1569: [65152, 0, 0, 0],
108
+ 1570: [65153, 65154, 0, 0],
109
+ 1571: [65155, 65156, 0, 0],
110
+ 1572: [65157, 65158, 0, 0],
111
+ 1573: [65159, 65160, 0, 0],
112
+ 1574: [65161, 65162, 65163, 65164],
113
+ 1575: [65165, 65166, 0, 0],
114
+ 1576: [65167, 65168, 65169, 65170],
115
+ 1577: [65171, 65172, 0, 0],
116
+ 1578: [65173, 65174, 65175, 65176],
117
+ 1579: [65177, 65178, 65179, 65180],
118
+ 1580: [65181, 65182, 65183, 65184],
119
+ 1581: [65185, 65186, 65187, 65188],
120
+ 1582: [65189, 65190, 65191, 65192],
121
+ 1583: [65193, 65194, 0, 0],
122
+ 1584: [65195, 65196, 0, 0],
123
+ 1585: [65197, 65198, 0, 0],
124
+ 1586: [65199, 65200, 0, 0],
125
+ 1587: [65201, 65202, 65203, 65204],
126
+ 1588: [65205, 65206, 65207, 65208],
127
+ 1589: [65209, 65210, 65211, 65212],
128
+ 1590: [65213, 65214, 65215, 65216],
129
+ 1591: [65217, 65218, 65219, 65220],
130
+ 1592: [65221, 65222, 65223, 65224],
131
+ 1593: [65225, 65226, 65227, 65228],
132
+ 1594: [65229, 65230, 65231, 65232],
133
+ 1601: [65233, 65234, 65235, 65236],
134
+ 1602: [65237, 65238, 65239, 65240],
135
+ 1603: [65241, 65242, 65243, 65244],
136
+ 1604: [65245, 65246, 65247, 65248],
137
+ 1605: [65249, 65250, 65251, 65252],
138
+ 1606: [65253, 65254, 65255, 65256],
139
+ 1607: [65257, 65258, 65259, 65260],
140
+ 1608: [65261, 65262, 0, 0],
141
+ 1609: [65263, 65264, 64488, 64489],
142
+ 1610: [65265, 65266, 65267, 65268],
143
+ 1611: [65136, 0, 0, 65137],
144
+ 1612: [65138, 0, 0, 0],
145
+ 1613: [65140, 0, 0, 0],
146
+ 1614: [65142, 0, 0, 65143],
147
+ 1615: [65144, 0, 0, 65145],
148
+ 1616: [65146, 0, 0, 65147],
149
+ 1617: [65148, 0, 0, 65149],
150
+ 1618: [65150, 0, 0, 65151],
151
+ 1649: [64336, 64337, 0, 0],
152
+ 1655: [64477, 0, 0, 0],
153
+ 1657: [64358, 64359, 64360, 64361],
154
+ 1658: [64350, 64351, 64352, 64353],
155
+ 1659: [64338, 64339, 64340, 64341],
156
+ 1662: [64342, 64343, 64344, 64345],
157
+ 1663: [64354, 64355, 64356, 64357],
158
+ 1664: [64346, 64347, 64348, 64349],
159
+ 1667: [64374, 64375, 64376, 64377],
160
+ 1668: [64370, 64371, 64372, 64373],
161
+ 1670: [64378, 64379, 64380, 64381],
162
+ 1671: [64382, 64383, 64384, 64385],
163
+ 1672: [64392, 64393, 0, 0],
164
+ 1676: [64388, 64389, 0, 0],
165
+ 1677: [64386, 64387, 0, 0],
166
+ 1678: [64390, 64391, 0, 0],
167
+ 1681: [64396, 64397, 0, 0],
168
+ 1688: [64394, 64395, 0, 0],
169
+ 1700: [64362, 64363, 64364, 64365],
170
+ 1702: [64366, 64367, 64368, 64369],
171
+ 1705: [64398, 64399, 64400, 64401],
172
+ 1709: [64467, 64468, 64469, 64470],
173
+ 1711: [64402, 64403, 64404, 64405],
174
+ 1713: [64410, 64411, 64412, 64413],
175
+ 1715: [64406, 64407, 64408, 64409],
176
+ 1722: [64414, 64415, 0, 0],
177
+ 1723: [64416, 64417, 64418, 64419],
178
+ 1726: [64426, 64427, 64428, 64429],
179
+ 1728: [64420, 64421, 0, 0],
180
+ 1729: [64422, 64423, 64424, 64425],
181
+ 1733: [64480, 64481, 0, 0],
182
+ 1734: [64473, 64474, 0, 0],
183
+ 1735: [64471, 64472, 0, 0],
184
+ 1736: [64475, 64476, 0, 0],
185
+ 1737: [64482, 64483, 0, 0],
186
+ 1739: [64478, 64479, 0, 0],
187
+ 1740: [64508, 64509, 64510, 64511],
188
+ 1744: [64484, 64485, 64486, 64487],
189
+ 1746: [64430, 64431, 0, 0],
190
+ 1747: [64432, 64433, 0, 0]
191
+ };
192
+
193
+ /** The lam-alef ligatures, keyed by the pair of letters they replace, as `[isolated, final]`. */
194
+ const LIGATURES: Record<string, [number, number]> = {
195
+ '\u0644\u0622': [65269, 65270],
196
+ '\u0644\u0623': [65271, 65272],
197
+ '\u0644\u0625': [65273, 65274],
198
+ '\u0644\u0627': [65275, 65276]
199
+ };
200
+
201
+ /**
202
+ * How a character joins to the ones beside it. `D` joins on both sides, `R` only to the character
203
+ * before it, `L` only to the one after it, `C` joins without being written itself, `T` is skipped
204
+ * over entirely, and `U` does not join at all.
205
+ */
206
+ type JoiningType = 'R' | 'L' | 'D' | 'C' | 'U' | 'T';
207
+
208
+ /** Lam, the only letter written as a ligature with the letter after it. */
209
+ const LAM = 0x0644;
210
+
211
+ /**
212
+ * The blocks Arabic is written from, and the two blocks of shapes this rewrites letters into, so
213
+ * that text already shaped is looked at again.
214
+ */
215
+ const ARABIC = /[؀-ۿݐ-ݿࡰ-࢟ࢠ-ࣿﭐ-﷿ﹰ-]/;
216
+
217
+ /** The shape a letter takes, as an index into its entry in `PRESENTATION_FORMS`. */
218
+ const ISOLATED = 0;
219
+ const FINAL = 1;
220
+ const INITIAL = 2;
221
+ const MEDIAL = 3;
222
+ type Form = typeof ISOLATED | typeof FINAL | typeof INITIAL | typeof MEDIAL;
223
+
224
+ /** One character of the text, with the shape the joining rules gave it. */
225
+ type ShapedCharacter = {
226
+ codePoint: number;
227
+ type: JoiningType;
228
+ form: Form | null;
229
+ };
230
+
231
+ /** Unpacks the delta-encoded ranges of one joining type into the code points they stand for. */
232
+ function decodeRanges(encoded: string, type: JoiningType, into: Map<number, JoiningType>): void {
233
+ let previousEnd = 0;
234
+ for (const range of encoded.split(';')) {
235
+ const [delta, length] = range.split(',').map(value => parseInt(value, 36));
236
+ const start = previousEnd + delta;
237
+ for (let codePoint = start; codePoint < start + length; codePoint++) {
238
+ into.set(codePoint, type);
239
+ }
240
+ previousEnd = start + length;
241
+ }
242
+ }
243
+
244
+ let joiningTypes: Map<number, JoiningType> | null = null;
245
+
246
+ /** The joining type of a code point; anything the Unicode database gives none stands alone. */
247
+ function joiningType(codePoint: number): JoiningType {
248
+ if (!joiningTypes) {
249
+ joiningTypes = new Map();
250
+ for (const [type, encoded] of Object.entries(ENCODED_JOINING_TYPES)) {
251
+ decodeRanges(encoded, type as JoiningType, joiningTypes);
252
+ }
253
+ }
254
+ return joiningTypes.get(codePoint) ?? 'U';
255
+ }
256
+
257
+ /** Whether the character before this one reaches forward to touch it. */
258
+ function joinsForward(type: JoiningType): boolean {
259
+ return type === 'D' || type === 'L' || type === 'C';
260
+ }
261
+
262
+ /** Whether the character after this one reaches back to touch it. */
263
+ function joinsBackward(type: JoiningType): boolean {
264
+ return type === 'D' || type === 'R' || type === 'C';
265
+ }
266
+
267
+ /**
268
+ * The shape a letter takes given what it can reach on either side. A letter that never joins is
269
+ * left as it was written.
270
+ */
271
+ function formFor(type: JoiningType, joinedBefore: boolean, joinedAfter: boolean): Form | null {
272
+ if (type === 'D') {
273
+ if (joinedBefore && joinedAfter) return MEDIAL;
274
+ if (joinedBefore) return FINAL;
275
+ if (joinedAfter) return INITIAL;
276
+ return ISOLATED;
277
+ }
278
+ if (type === 'R') return joinedBefore ? FINAL : ISOLATED;
279
+ if (type === 'L') return joinedAfter ? INITIAL : ISOLATED;
280
+ return null;
281
+ }
282
+
283
+ /**
284
+ * Works out the shape of every letter. Transparent characters (vowel points) are looked straight
285
+ * through, so a letter joins to its neighbour across them.
286
+ */
287
+ function assignLetterForms(characters: ShapedCharacter[]): void {
288
+ const visible = characters.filter(character => character.type !== 'T');
289
+ for (let i = 0; i < visible.length; i++) {
290
+ const joinedBefore = i > 0 && joinsForward(visible[i - 1].type);
291
+ const joinedAfter = i + 1 < visible.length && joinsBackward(visible[i + 1].type);
292
+ visible[i].form = formFor(visible[i].type, joinedBefore, joinedAfter);
293
+ }
294
+ }
295
+
296
+ /** Gives each vowel point the shape it takes over its letter: medial where the letter joins on. */
297
+ function assignMarkForms(characters: ShapedCharacter[]): void {
298
+ let letterJoinsForward = false;
299
+ for (const character of characters) {
300
+ if (character.type === 'T') {
301
+ character.form = letterJoinsForward ? MEDIAL : ISOLATED;
302
+ } else {
303
+ letterJoinsForward = character.form === INITIAL || character.form === MEDIAL;
304
+ }
305
+ }
306
+ }
307
+
308
+ /**
309
+ * Replaces each lam followed by an alef with their ligature: final when the lam joined the letter
310
+ * before it, isolated otherwise. Vowel points between the two follow the ligature.
311
+ */
312
+ function applyLigatures(characters: ShapedCharacter[]): ShapedCharacter[] {
313
+ const result: ShapedCharacter[] = [];
314
+ for (let i = 0; i < characters.length; i++) {
315
+ const lam = characters[i];
316
+ if (lam.codePoint !== LAM) {
317
+ result.push(lam);
318
+ continue;
319
+ }
320
+ let next = i + 1;
321
+ while (next < characters.length && characters[next].type === 'T') next++;
322
+ const alef = characters[next];
323
+ const ligature = alef && LIGATURES[String.fromCodePoint(LAM, alef.codePoint)];
324
+ if (!ligature) {
325
+ result.push(lam);
326
+ continue;
327
+ }
328
+ const joinedBefore = lam.form === MEDIAL || lam.form === FINAL;
329
+ result.push({codePoint: ligature[joinedBefore ? 1 : 0], type: 'R', form: ISOLATED});
330
+ // One at a time: spreading a long run of marks from tile text would overflow the call stack.
331
+ for (let k = i + 1; k < next; k++) {
332
+ result.push(characters[k]);
333
+ }
334
+ i = next;
335
+ }
336
+ return result;
337
+ }
338
+
339
+ /** The presentation form of a character, or the character itself where there is none. */
340
+ function toPresentationForm(character: ShapedCharacter): number {
341
+ if (character.form === null) return character.codePoint;
342
+ const forms = PRESENTATION_FORMS[character.codePoint];
343
+ if (!forms) return character.codePoint;
344
+ return forms[character.form] || forms[ISOLATED] || character.codePoint;
345
+ }
346
+
347
+ /**
348
+ * Rewrites Arabic letters as the shape they take in their word, named by their Arabic
349
+ * Presentation Forms code points (U+FB50–FDFF, U+FE70–FEFF), with lam-alef ligatures, as MapLibre
350
+ * GL JS does: glyphs are drawn one code point at a time, so the contextual shape has to be chosen
351
+ * before glyphs are looked up. Text with no Arabic in it is returned unchanged.
352
+ */
353
+ export function applyArabicShaping(text: string): string {
354
+ if (!ARABIC.test(text)) {
355
+ return text;
356
+ }
357
+ const characters = Array.from(text, character => {
358
+ const codePoint = character.codePointAt(0)!;
359
+ return {codePoint, type: joiningType(codePoint), form: null} as ShapedCharacter;
360
+ });
361
+ assignLetterForms(characters);
362
+ assignMarkForms(characters);
363
+ return applyLigatures(characters)
364
+ .map(character => String.fromCodePoint(toPresentationForm(character)))
365
+ .join('');
366
+ }
@@ -0,0 +1,19 @@
1
+ // tangram-layers
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ /**
6
+ * Returns the top-of-globe atmosphere overlay layer when atmosphere rendering
7
+ * is enabled.
8
+ */
9
+ export function getGlobeAtmosphereLayer() {
10
+ return null;
11
+ }
12
+
13
+ /**
14
+ * Returns the background sky layer rendered behind the globe when atmosphere
15
+ * rendering is enabled.
16
+ */
17
+ export function getGlobeAtmosphereSkyLayer() {
18
+ return null;
19
+ }