@mapwhit/tilerenderer 0.47.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.
- package/LICENSE.txt +87 -0
- package/README.md +25 -0
- package/build/min/.dir +0 -0
- package/build/min/package.json +3 -0
- package/build/min/src/shaders/_prelude.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/_prelude.vertex.glsl.txt +14 -0
- package/build/min/src/shaders/background.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/background.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/background_pattern.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/background_pattern.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/circle.fragment.glsl.txt +20 -0
- package/build/min/src/shaders/circle.vertex.glsl.txt +17 -0
- package/build/min/src/shaders/clipping_mask.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/clipping_mask.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/collision_box.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/collision_box.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/collision_circle.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/collision_circle.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/debug.fragment.glsl.txt +1 -0
- package/build/min/src/shaders/debug.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/fill.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/fill.vertex.glsl.txt +7 -0
- package/build/min/src/shaders/fill_extrusion.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_extrusion.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.txt +15 -0
- package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.txt +11 -0
- package/build/min/src/shaders/fill_outline.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/fill_outline.vertex.glsl.txt +7 -0
- package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/fill_pattern.fragment.glsl.txt +13 -0
- package/build/min/src/shaders/fill_pattern.vertex.glsl.txt +9 -0
- package/build/min/src/shaders/heatmap.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/heatmap.vertex.glsl.txt +8 -0
- package/build/min/src/shaders/heatmap_texture.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/heatmap_texture.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/hillshade.fragment.glsl.txt +7 -0
- package/build/min/src/shaders/hillshade.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/hillshade_prepare.fragment.glsl.txt +8 -0
- package/build/min/src/shaders/hillshade_prepare.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/line.fragment.glsl.txt +12 -0
- package/build/min/src/shaders/line.vertex.glsl.txt +17 -0
- package/build/min/src/shaders/line_gradient.fragment.glsl.txt +10 -0
- package/build/min/src/shaders/line_gradient.vertex.glsl.txt +16 -0
- package/build/min/src/shaders/line_pattern.fragment.glsl.txt +15 -0
- package/build/min/src/shaders/line_pattern.vertex.glsl.txt +20 -0
- package/build/min/src/shaders/line_sdf.fragment.glsl.txt +17 -0
- package/build/min/src/shaders/line_sdf.vertex.glsl.txt +20 -0
- package/build/min/src/shaders/raster.fragment.glsl.txt +5 -0
- package/build/min/src/shaders/raster.vertex.glsl.txt +1 -0
- package/build/min/src/shaders/symbol_icon.fragment.glsl.txt +9 -0
- package/build/min/src/shaders/symbol_icon.vertex.glsl.txt +5 -0
- package/build/min/src/shaders/symbol_sdf.fragment.glsl.txt +19 -0
- package/build/min/src/shaders/symbol_sdf.vertex.glsl.txt +13 -0
- package/package.json +44 -0
- package/src/css/mapbox-gl.css +506 -0
- package/src/css/svg/mapboxgl-ctrl-attrib.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-compass.svg +4 -0
- package/src/css/svg/mapboxgl-ctrl-fullscreen.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-geolocate-background.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-geolocate.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-logo-compact.svg +2 -0
- package/src/css/svg/mapboxgl-ctrl-logo.svg +1 -0
- package/src/css/svg/mapboxgl-ctrl-shrink.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-zoom-in.svg +3 -0
- package/src/css/svg/mapboxgl-ctrl-zoom-out.svg +3 -0
- package/src/data/array_types.js +1138 -0
- package/src/data/bucket/circle_attributes.js +5 -0
- package/src/data/bucket/circle_bucket.js +118 -0
- package/src/data/bucket/fill_attributes.js +5 -0
- package/src/data/bucket/fill_bucket.js +166 -0
- package/src/data/bucket/fill_extrusion_attributes.js +11 -0
- package/src/data/bucket/fill_extrusion_bucket.js +247 -0
- package/src/data/bucket/heatmap_bucket.js +12 -0
- package/src/data/bucket/line_attributes.js +11 -0
- package/src/data/bucket/line_bucket.js +625 -0
- package/src/data/bucket/pattern_attributes.js +9 -0
- package/src/data/bucket/pattern_bucket_features.js +44 -0
- package/src/data/bucket/symbol_attributes.js +95 -0
- package/src/data/bucket/symbol_bucket.js +697 -0
- package/src/data/bucket.js +53 -0
- package/src/data/dem_data.js +126 -0
- package/src/data/extent.js +17 -0
- package/src/data/feature_index.js +254 -0
- package/src/data/index_array_type.js +14 -0
- package/src/data/load_geometry.js +42 -0
- package/src/data/pos_attributes.js +3 -0
- package/src/data/program_configuration.js +782 -0
- package/src/data/raster_bounds_attributes.js +6 -0
- package/src/data/segment.js +63 -0
- package/src/geo/coordinate.js +78 -0
- package/src/geo/lng_lat.js +129 -0
- package/src/geo/lng_lat_bounds.js +253 -0
- package/src/geo/transform.js +605 -0
- package/src/gl/color_mode.js +21 -0
- package/src/gl/context.js +193 -0
- package/src/gl/cull_face_mode.js +22 -0
- package/src/gl/depth_mode.js +18 -0
- package/src/gl/framebuffer.js +28 -0
- package/src/gl/index_buffer.js +52 -0
- package/src/gl/stencil_mode.js +17 -0
- package/src/gl/types.js +0 -0
- package/src/gl/value.js +676 -0
- package/src/gl/vertex_buffer.js +101 -0
- package/src/index.js +50 -0
- package/src/render/draw_background.js +60 -0
- package/src/render/draw_circle.js +55 -0
- package/src/render/draw_collision_debug.js +45 -0
- package/src/render/draw_debug.js +429 -0
- package/src/render/draw_fill.js +143 -0
- package/src/render/draw_fill_extrusion.js +101 -0
- package/src/render/draw_heatmap.js +159 -0
- package/src/render/draw_hillshade.js +144 -0
- package/src/render/draw_line.js +99 -0
- package/src/render/draw_raster.js +151 -0
- package/src/render/draw_symbol.js +231 -0
- package/src/render/glyph_atlas.js +55 -0
- package/src/render/glyph_manager.js +145 -0
- package/src/render/image_atlas.js +97 -0
- package/src/render/image_manager.js +183 -0
- package/src/render/line_atlas.js +139 -0
- package/src/render/painter.js +483 -0
- package/src/render/program/background_program.js +46 -0
- package/src/render/program/circle_program.js +40 -0
- package/src/render/program/clipping_mask_program.js +11 -0
- package/src/render/program/collision_program.js +28 -0
- package/src/render/program/debug_program.js +13 -0
- package/src/render/program/fill_extrusion_program.js +76 -0
- package/src/render/program/fill_program.js +60 -0
- package/src/render/program/heatmap_program.js +46 -0
- package/src/render/program/hillshade_program.js +77 -0
- package/src/render/program/line_program.js +119 -0
- package/src/render/program/pattern.js +57 -0
- package/src/render/program/program_uniforms.js +46 -0
- package/src/render/program/raster_program.js +50 -0
- package/src/render/program/symbol_program.js +112 -0
- package/src/render/program.js +133 -0
- package/src/render/texture.js +88 -0
- package/src/render/tile_mask.js +108 -0
- package/src/render/uniform_binding.js +129 -0
- package/src/render/vertex_array_object.js +155 -0
- package/src/shaders/README.md +42 -0
- package/src/shaders/_prelude.fragment.glsl +17 -0
- package/src/shaders/_prelude.vertex.glsl +73 -0
- package/src/shaders/background.fragment.glsl +10 -0
- package/src/shaders/background.vertex.glsl +7 -0
- package/src/shaders/background_pattern.fragment.glsl +28 -0
- package/src/shaders/background_pattern.vertex.glsl +20 -0
- package/src/shaders/circle.fragment.glsl +39 -0
- package/src/shaders/circle.vertex.glsl +63 -0
- package/src/shaders/clipping_mask.fragment.glsl +3 -0
- package/src/shaders/clipping_mask.vertex.glsl +7 -0
- package/src/shaders/collision_box.fragment.glsl +21 -0
- package/src/shaders/collision_box.vertex.glsl +26 -0
- package/src/shaders/collision_circle.fragment.glsl +34 -0
- package/src/shaders/collision_circle.vertex.glsl +36 -0
- package/src/shaders/debug.fragment.glsl +5 -0
- package/src/shaders/debug.vertex.glsl +7 -0
- package/src/shaders/encode_attribute.js +19 -0
- package/src/shaders/fill.fragment.glsl +13 -0
- package/src/shaders/fill.vertex.glsl +13 -0
- package/src/shaders/fill_extrusion.fragment.glsl +16 -0
- package/src/shaders/fill_extrusion.vertex.glsl +66 -0
- package/src/shaders/fill_extrusion_pattern.fragment.glsl +41 -0
- package/src/shaders/fill_extrusion_pattern.vertex.glsl +76 -0
- package/src/shaders/fill_outline.fragment.glsl +17 -0
- package/src/shaders/fill_outline.vertex.glsl +17 -0
- package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
- package/src/shaders/fill_outline_pattern.vertex.glsl +41 -0
- package/src/shaders/fill_pattern.fragment.glsl +36 -0
- package/src/shaders/fill_pattern.vertex.glsl +36 -0
- package/src/shaders/heatmap.fragment.glsl +21 -0
- package/src/shaders/heatmap.vertex.glsl +53 -0
- package/src/shaders/heatmap_texture.fragment.glsl +14 -0
- package/src/shaders/heatmap_texture.vertex.glsl +11 -0
- package/src/shaders/hillshade.fragment.glsl +52 -0
- package/src/shaders/hillshade.vertex.glsl +11 -0
- package/src/shaders/hillshade_prepare.fragment.glsl +72 -0
- package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
- package/src/shaders/index.js +194 -0
- package/src/shaders/line.fragment.glsl +28 -0
- package/src/shaders/line.vertex.glsl +84 -0
- package/src/shaders/line_gradient.fragment.glsl +34 -0
- package/src/shaders/line_gradient.vertex.glsl +84 -0
- package/src/shaders/line_pattern.fragment.glsl +69 -0
- package/src/shaders/line_pattern.vertex.glsl +88 -0
- package/src/shaders/line_sdf.fragment.glsl +44 -0
- package/src/shaders/line_sdf.vertex.glsl +95 -0
- package/src/shaders/raster.fragment.glsl +52 -0
- package/src/shaders/raster.vertex.glsl +21 -0
- package/src/shaders/symbol_icon.fragment.glsl +17 -0
- package/src/shaders/symbol_icon.vertex.glsl +91 -0
- package/src/shaders/symbol_sdf.fragment.glsl +50 -0
- package/src/shaders/symbol_sdf.vertex.glsl +117 -0
- package/src/source/geojson_source.js +267 -0
- package/src/source/geojson_worker_source.js +210 -0
- package/src/source/geojson_wrapper.js +67 -0
- package/src/source/image_source.js +213 -0
- package/src/source/load_tilejson.js +40 -0
- package/src/source/pixels_to_tile_units.js +17 -0
- package/src/source/query_features.js +198 -0
- package/src/source/raster_dem_tile_source.js +140 -0
- package/src/source/raster_dem_tile_worker_source.js +26 -0
- package/src/source/raster_tile_source.js +126 -0
- package/src/source/rtl_text_plugin.js +63 -0
- package/src/source/source.js +75 -0
- package/src/source/source_cache.js +794 -0
- package/src/source/source_state.js +55 -0
- package/src/source/tile.js +332 -0
- package/src/source/tile_bounds.js +40 -0
- package/src/source/tile_cache.js +122 -0
- package/src/source/tile_id.js +150 -0
- package/src/source/vector_tile_source.js +144 -0
- package/src/source/vector_tile_worker_source.js +126 -0
- package/src/source/worker.js +175 -0
- package/src/source/worker_source.js +14 -0
- package/src/source/worker_tile.js +199 -0
- package/src/style/create_style_layer.js +25 -0
- package/src/style/evaluation_parameters.js +45 -0
- package/src/style/light.js +112 -0
- package/src/style/load_glyph_range.js +17 -0
- package/src/style/load_sprite.js +26 -0
- package/src/style/parse_glyph_pbf.js +45 -0
- package/src/style/pauseable_placement.js +88 -0
- package/src/style/properties.js +691 -0
- package/src/style/query_utils.js +39 -0
- package/src/style/style.js +955 -0
- package/src/style/style_layer/background_style_layer.js +11 -0
- package/src/style/style_layer/background_style_layer_properties.js +25 -0
- package/src/style/style_layer/circle_style_layer.js +93 -0
- package/src/style/style_layer/circle_style_layer_properties.js +76 -0
- package/src/style/style_layer/fill_extrusion_style_layer.js +194 -0
- package/src/style/style_layer/fill_extrusion_style_layer_properties.js +56 -0
- package/src/style/style_layer/fill_style_layer.js +46 -0
- package/src/style/style_layer/fill_style_layer_properties.js +45 -0
- package/src/style/style_layer/heatmap_style_layer.js +51 -0
- package/src/style/style_layer/heatmap_style_layer_properties.js +52 -0
- package/src/style/style_layer/hillshade_style_layer.js +15 -0
- package/src/style/style_layer/hillshade_style_layer_properties.js +43 -0
- package/src/style/style_layer/line_style_layer.js +129 -0
- package/src/style/style_layer/line_style_layer_properties.js +104 -0
- package/src/style/style_layer/raster_style_layer.js +11 -0
- package/src/style/style_layer/raster_style_layer_properties.js +55 -0
- package/src/style/style_layer/symbol_style_layer.js +66 -0
- package/src/style/style_layer/symbol_style_layer_properties.js +288 -0
- package/src/style/style_layer.js +183 -0
- package/src/style/style_layer_index.js +61 -0
- package/src/style/zoom_history.js +36 -0
- package/src/style-spec/deref.js +51 -0
- package/src/style-spec/error/parsing_error.js +8 -0
- package/src/style-spec/error/validation_error.js +10 -0
- package/src/style-spec/expression/compound_expression.js +118 -0
- package/src/style-spec/expression/definitions/array.js +82 -0
- package/src/style-spec/expression/definitions/assertion.js +69 -0
- package/src/style-spec/expression/definitions/at.js +57 -0
- package/src/style-spec/expression/definitions/case.js +73 -0
- package/src/style-spec/expression/definitions/coalesce.js +68 -0
- package/src/style-spec/expression/definitions/coercion.js +96 -0
- package/src/style-spec/expression/definitions/collator.js +102 -0
- package/src/style-spec/expression/definitions/equals.js +93 -0
- package/src/style-spec/expression/definitions/index.js +407 -0
- package/src/style-spec/expression/definitions/interpolate.js +235 -0
- package/src/style-spec/expression/definitions/length.js +54 -0
- package/src/style-spec/expression/definitions/let.js +60 -0
- package/src/style-spec/expression/definitions/literal.js +64 -0
- package/src/style-spec/expression/definitions/match.js +142 -0
- package/src/style-spec/expression/definitions/step.js +116 -0
- package/src/style-spec/expression/definitions/var.js +38 -0
- package/src/style-spec/expression/evaluation_context.js +35 -0
- package/src/style-spec/expression/index.js +329 -0
- package/src/style-spec/expression/is_constant.js +63 -0
- package/src/style-spec/expression/parsing_context.js +213 -0
- package/src/style-spec/expression/parsing_error.js +9 -0
- package/src/style-spec/expression/runtime_error.js +12 -0
- package/src/style-spec/expression/scope.js +34 -0
- package/src/style-spec/expression/stops.js +37 -0
- package/src/style-spec/expression/types.js +77 -0
- package/src/style-spec/expression/values.js +126 -0
- package/src/style-spec/feature_filter/README.md +55 -0
- package/src/style-spec/feature_filter/index.js +158 -0
- package/src/style-spec/function/convert.js +256 -0
- package/src/style-spec/function/index.js +299 -0
- package/src/style-spec/group_by_layout.js +68 -0
- package/src/style-spec/reference/v8.json +5356 -0
- package/src/style-spec/util/color.js +73 -0
- package/src/style-spec/util/color_spaces.js +128 -0
- package/src/style-spec/util/eval_support.js +8 -0
- package/src/style-spec/util/get_type.js +18 -0
- package/src/style-spec/util/interpolate.js +21 -0
- package/src/style-spec/util/properties.js +17 -0
- package/src/style-spec/util/ref_properties.js +1 -0
- package/src/style-spec/util/result.js +19 -0
- package/src/symbol/anchor.js +21 -0
- package/src/symbol/check_max_angle.js +75 -0
- package/src/symbol/clip_line.js +73 -0
- package/src/symbol/collision_feature.js +230 -0
- package/src/symbol/collision_index.js +379 -0
- package/src/symbol/cross_tile_symbol_index.js +270 -0
- package/src/symbol/get_anchors.js +177 -0
- package/src/symbol/grid_index.js +318 -0
- package/src/symbol/mergelines.js +75 -0
- package/src/symbol/opacity_state.js +21 -0
- package/src/symbol/placement.js +563 -0
- package/src/symbol/projection.js +601 -0
- package/src/symbol/quads.js +173 -0
- package/src/symbol/shaping.js +347 -0
- package/src/symbol/symbol_layout.js +519 -0
- package/src/symbol/symbol_size.js +110 -0
- package/src/symbol/transform_text.js +16 -0
- package/src/ui/anchor.js +24 -0
- package/src/ui/bind_handlers.js +199 -0
- package/src/ui/camera.js +954 -0
- package/src/ui/events.js +210 -0
- package/src/ui/handler/box_zoom.js +151 -0
- package/src/ui/handler/dblclick_zoom.js +91 -0
- package/src/ui/handler/drag_pan.js +285 -0
- package/src/ui/handler/drag_rotate.js +290 -0
- package/src/ui/handler/frame.js +28 -0
- package/src/ui/handler/inertia.js +45 -0
- package/src/ui/handler/keyboard.js +148 -0
- package/src/ui/handler/scroll_zoom.js +284 -0
- package/src/ui/handler/touch_zoom_rotate.js +263 -0
- package/src/ui/map.js +1645 -0
- package/src/util/actor.js +104 -0
- package/src/util/async.js +23 -0
- package/src/util/browser.js +61 -0
- package/src/util/callback.js +26 -0
- package/src/util/classify_rings.js +43 -0
- package/src/util/color_ramp.js +24 -0
- package/src/util/config.js +24 -0
- package/src/util/dictionary_coder.js +25 -0
- package/src/util/dispatcher.js +68 -0
- package/src/util/dom.js +102 -0
- package/src/util/evented.js +182 -0
- package/src/util/find_pole_of_inaccessibility.js +129 -0
- package/src/util/global_worker_pool.js +15 -0
- package/src/util/image.js +124 -0
- package/src/util/interpolate.js +5 -0
- package/src/util/intersection_tests.js +207 -0
- package/src/util/is_char_in_unicode_block.js +287 -0
- package/src/util/loader/image.js +32 -0
- package/src/util/object.js +178 -0
- package/src/util/script_detection.js +337 -0
- package/src/util/struct_array.js +197 -0
- package/src/util/task_queue.js +57 -0
- package/src/util/throttle.js +26 -0
- package/src/util/tile_cover.js +114 -0
- package/src/util/token.js +13 -0
- package/src/util/unique_id.js +12 -0
- package/src/util/util.js +192 -0
- package/src/util/vectortile_to_geojson.js +44 -0
- package/src/util/verticalize_punctuation.js +112 -0
- package/src/util/warn.js +21 -0
- package/src/util/web_worker.js +5 -0
- package/src/util/web_worker_transfer.js +228 -0
- package/src/util/worker_pool.js +41 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
const drawCollisionDebug = require('./draw_collision_debug');
|
|
2
|
+
|
|
3
|
+
const pixelsToTileUnits = require('../source/pixels_to_tile_units');
|
|
4
|
+
const symbolProjection = require('../symbol/projection');
|
|
5
|
+
const symbolSize = require('../symbol/symbol_size');
|
|
6
|
+
const { mat4 } = require('@mapbox/gl-matrix');
|
|
7
|
+
const identityMat4 = mat4.identity(new Float32Array(16));
|
|
8
|
+
const properties = require('../style/style_layer/symbol_style_layer_properties');
|
|
9
|
+
const symbolLayoutProperties = properties.layout;
|
|
10
|
+
const StencilMode = require('../gl/stencil_mode');
|
|
11
|
+
const DepthMode = require('../gl/depth_mode');
|
|
12
|
+
const CullFaceMode = require('../gl/cull_face_mode');
|
|
13
|
+
const { symbolIconUniformValues, symbolSDFUniformValues } = require('./program/symbol_program');
|
|
14
|
+
|
|
15
|
+
module.exports = drawSymbols;
|
|
16
|
+
|
|
17
|
+
function drawSymbols(painter, sourceCache, layer, coords) {
|
|
18
|
+
if (painter.renderPass !== 'translucent') return;
|
|
19
|
+
|
|
20
|
+
// Disable the stencil test so that labels aren't clipped to tile boundaries.
|
|
21
|
+
const stencilMode = StencilMode.disabled;
|
|
22
|
+
const colorMode = painter.colorModeForRenderPass();
|
|
23
|
+
|
|
24
|
+
if (layer.paint.get('icon-opacity').constantOr(1) !== 0) {
|
|
25
|
+
drawLayerSymbols(
|
|
26
|
+
painter,
|
|
27
|
+
sourceCache,
|
|
28
|
+
layer,
|
|
29
|
+
coords,
|
|
30
|
+
false,
|
|
31
|
+
layer.paint.get('icon-translate'),
|
|
32
|
+
layer.paint.get('icon-translate-anchor'),
|
|
33
|
+
layer.layout.get('icon-rotation-alignment'),
|
|
34
|
+
layer.layout.get('icon-pitch-alignment'),
|
|
35
|
+
layer.layout.get('icon-keep-upright'),
|
|
36
|
+
stencilMode,
|
|
37
|
+
colorMode
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (layer.paint.get('text-opacity').constantOr(1) !== 0) {
|
|
42
|
+
drawLayerSymbols(
|
|
43
|
+
painter,
|
|
44
|
+
sourceCache,
|
|
45
|
+
layer,
|
|
46
|
+
coords,
|
|
47
|
+
true,
|
|
48
|
+
layer.paint.get('text-translate'),
|
|
49
|
+
layer.paint.get('text-translate-anchor'),
|
|
50
|
+
layer.layout.get('text-rotation-alignment'),
|
|
51
|
+
layer.layout.get('text-pitch-alignment'),
|
|
52
|
+
layer.layout.get('text-keep-upright'),
|
|
53
|
+
stencilMode,
|
|
54
|
+
colorMode
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (sourceCache.map.showCollisionBoxes) {
|
|
59
|
+
drawCollisionDebug(painter, sourceCache, layer, coords);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function drawLayerSymbols(
|
|
64
|
+
painter,
|
|
65
|
+
sourceCache,
|
|
66
|
+
layer,
|
|
67
|
+
coords,
|
|
68
|
+
isText,
|
|
69
|
+
translate,
|
|
70
|
+
translateAnchor,
|
|
71
|
+
rotationAlignment,
|
|
72
|
+
pitchAlignment,
|
|
73
|
+
keepUpright,
|
|
74
|
+
stencilMode,
|
|
75
|
+
colorMode
|
|
76
|
+
) {
|
|
77
|
+
const context = painter.context;
|
|
78
|
+
const gl = context.gl;
|
|
79
|
+
const tr = painter.transform;
|
|
80
|
+
|
|
81
|
+
const rotateWithMap = rotationAlignment === 'map';
|
|
82
|
+
const pitchWithMap = pitchAlignment === 'map';
|
|
83
|
+
const alongLine = rotateWithMap && layer.layout.get('symbol-placement') !== 'point';
|
|
84
|
+
// Line label rotation happens in `updateLineLabels`
|
|
85
|
+
// Pitched point labels are automatically rotated by the labelPlaneMatrix projection
|
|
86
|
+
// Unpitched point labels need to have their rotation applied after projection
|
|
87
|
+
const rotateInShader = rotateWithMap && !pitchWithMap && !alongLine;
|
|
88
|
+
|
|
89
|
+
const depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly);
|
|
90
|
+
|
|
91
|
+
let program;
|
|
92
|
+
let size;
|
|
93
|
+
|
|
94
|
+
for (const coord of coords) {
|
|
95
|
+
const tile = sourceCache.getTile(coord);
|
|
96
|
+
const bucket = tile.getBucket(layer);
|
|
97
|
+
if (!bucket) continue;
|
|
98
|
+
const buffers = isText ? bucket.text : bucket.icon;
|
|
99
|
+
if (!buffers || !buffers.segments.get().length) continue;
|
|
100
|
+
const programConfiguration = buffers.programConfigurations.get(layer.id);
|
|
101
|
+
|
|
102
|
+
const isSDF = isText || bucket.sdfIcons;
|
|
103
|
+
|
|
104
|
+
const sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
|
|
105
|
+
|
|
106
|
+
if (!program) {
|
|
107
|
+
program = painter.useProgram(isSDF ? 'symbolSDF' : 'symbolIcon', programConfiguration);
|
|
108
|
+
size = symbolSize.evaluateSizeForZoom(
|
|
109
|
+
sizeData,
|
|
110
|
+
tr.zoom,
|
|
111
|
+
symbolLayoutProperties.properties[isText ? 'text-size' : 'icon-size']
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
context.activeTexture.set(gl.TEXTURE0);
|
|
116
|
+
|
|
117
|
+
let texSize;
|
|
118
|
+
if (isText) {
|
|
119
|
+
tile.glyphAtlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
|
|
120
|
+
texSize = tile.glyphAtlasTexture.size;
|
|
121
|
+
} else {
|
|
122
|
+
const iconScaled = layer.layout.get('icon-size').constantOr(0) !== 1 || bucket.iconsNeedLinear;
|
|
123
|
+
const iconTransformed = pitchWithMap || tr.pitch !== 0;
|
|
124
|
+
|
|
125
|
+
tile.imageAtlasTexture.bind(
|
|
126
|
+
isSDF || painter.options.rotating || painter.options.zooming || iconScaled || iconTransformed
|
|
127
|
+
? gl.LINEAR
|
|
128
|
+
: gl.NEAREST,
|
|
129
|
+
gl.CLAMP_TO_EDGE
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
texSize = tile.imageAtlasTexture.size;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const s = pixelsToTileUnits(tile, 1, painter.transform.zoom);
|
|
136
|
+
const labelPlaneMatrix = symbolProjection.getLabelPlaneMatrix(
|
|
137
|
+
coord.posMatrix,
|
|
138
|
+
pitchWithMap,
|
|
139
|
+
rotateWithMap,
|
|
140
|
+
painter.transform,
|
|
141
|
+
s
|
|
142
|
+
);
|
|
143
|
+
const glCoordMatrix = symbolProjection.getGlCoordMatrix(
|
|
144
|
+
coord.posMatrix,
|
|
145
|
+
pitchWithMap,
|
|
146
|
+
rotateWithMap,
|
|
147
|
+
painter.transform,
|
|
148
|
+
s
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (alongLine) {
|
|
152
|
+
symbolProjection.updateLineLabels(
|
|
153
|
+
bucket,
|
|
154
|
+
coord.posMatrix,
|
|
155
|
+
painter,
|
|
156
|
+
isText,
|
|
157
|
+
labelPlaneMatrix,
|
|
158
|
+
glCoordMatrix,
|
|
159
|
+
pitchWithMap,
|
|
160
|
+
keepUpright
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor);
|
|
165
|
+
const uLabelPlaneMatrix = alongLine ? identityMat4 : labelPlaneMatrix;
|
|
166
|
+
const uglCoordMatrix = painter.translatePosMatrix(glCoordMatrix, tile, translate, translateAnchor, true);
|
|
167
|
+
|
|
168
|
+
let uniformValues;
|
|
169
|
+
if (isSDF) {
|
|
170
|
+
const hasHalo = layer.paint.get(isText ? 'text-halo-width' : 'icon-halo-width').constantOr(1) !== 0;
|
|
171
|
+
|
|
172
|
+
uniformValues = symbolSDFUniformValues(
|
|
173
|
+
sizeData.functionType,
|
|
174
|
+
size,
|
|
175
|
+
rotateInShader,
|
|
176
|
+
pitchWithMap,
|
|
177
|
+
painter,
|
|
178
|
+
matrix,
|
|
179
|
+
uLabelPlaneMatrix,
|
|
180
|
+
uglCoordMatrix,
|
|
181
|
+
isText,
|
|
182
|
+
texSize,
|
|
183
|
+
true
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
if (hasHalo) {
|
|
187
|
+
drawSymbolElements(buffers, layer, painter, program, depthMode, stencilMode, colorMode, uniformValues);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
uniformValues['u_is_halo'] = 0;
|
|
191
|
+
} else {
|
|
192
|
+
uniformValues = symbolIconUniformValues(
|
|
193
|
+
sizeData.functionType,
|
|
194
|
+
size,
|
|
195
|
+
rotateInShader,
|
|
196
|
+
pitchWithMap,
|
|
197
|
+
painter,
|
|
198
|
+
matrix,
|
|
199
|
+
uLabelPlaneMatrix,
|
|
200
|
+
uglCoordMatrix,
|
|
201
|
+
isText,
|
|
202
|
+
texSize
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
drawSymbolElements(buffers, layer, painter, program, depthMode, stencilMode, colorMode, uniformValues);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function drawSymbolElements(buffers, layer, painter, program, depthMode, stencilMode, colorMode, uniformValues) {
|
|
211
|
+
const context = painter.context;
|
|
212
|
+
const gl = context.gl;
|
|
213
|
+
program.draw(
|
|
214
|
+
context,
|
|
215
|
+
gl.TRIANGLES,
|
|
216
|
+
depthMode,
|
|
217
|
+
stencilMode,
|
|
218
|
+
colorMode,
|
|
219
|
+
CullFaceMode.disabled,
|
|
220
|
+
uniformValues,
|
|
221
|
+
layer.id,
|
|
222
|
+
buffers.layoutVertexBuffer,
|
|
223
|
+
buffers.indexBuffer,
|
|
224
|
+
buffers.segments,
|
|
225
|
+
layer.paint,
|
|
226
|
+
painter.transform.zoom,
|
|
227
|
+
buffers.programConfigurations.get(layer.id),
|
|
228
|
+
buffers.dynamicLayoutVertexBuffer,
|
|
229
|
+
buffers.opacityVertexBuffer
|
|
230
|
+
);
|
|
231
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const ShelfPack = require('@mapbox/shelf-pack');
|
|
2
|
+
|
|
3
|
+
const { AlphaImage } = require('../util/image');
|
|
4
|
+
const { register } = require('../util/web_worker_transfer');
|
|
5
|
+
|
|
6
|
+
const padding = 1;
|
|
7
|
+
|
|
8
|
+
class GlyphAtlas {
|
|
9
|
+
constructor(stacks) {
|
|
10
|
+
const positions = {};
|
|
11
|
+
const pack = new ShelfPack(0, 0, { autoResize: true });
|
|
12
|
+
const bins = [];
|
|
13
|
+
|
|
14
|
+
for (const stack in stacks) {
|
|
15
|
+
const glyphs = stacks[stack];
|
|
16
|
+
const stackPositions = (positions[stack] = {});
|
|
17
|
+
|
|
18
|
+
for (const id in glyphs) {
|
|
19
|
+
const src = glyphs[+id];
|
|
20
|
+
if (!src || src.bitmap.width === 0 || src.bitmap.height === 0) continue;
|
|
21
|
+
|
|
22
|
+
const bin = {
|
|
23
|
+
x: 0,
|
|
24
|
+
y: 0,
|
|
25
|
+
w: src.bitmap.width + 2 * padding,
|
|
26
|
+
h: src.bitmap.height + 2 * padding
|
|
27
|
+
};
|
|
28
|
+
bins.push(bin);
|
|
29
|
+
stackPositions[id] = { rect: bin, metrics: src.metrics };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pack.pack(bins, { inPlace: true });
|
|
34
|
+
|
|
35
|
+
const image = new AlphaImage({ width: pack.w, height: pack.h });
|
|
36
|
+
|
|
37
|
+
for (const stack in stacks) {
|
|
38
|
+
const glyphs = stacks[stack];
|
|
39
|
+
|
|
40
|
+
for (const id in glyphs) {
|
|
41
|
+
const src = glyphs[+id];
|
|
42
|
+
if (!src || src.bitmap.width === 0 || src.bitmap.height === 0) continue;
|
|
43
|
+
const bin = positions[stack][id].rect;
|
|
44
|
+
AlphaImage.copy(src.bitmap, image, { x: 0, y: 0 }, { x: bin.x + padding, y: bin.y + padding }, src.bitmap);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.image = image;
|
|
49
|
+
this.positions = positions;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
register('GlyphAtlas', GlyphAtlas);
|
|
54
|
+
|
|
55
|
+
module.exports = GlyphAtlas;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const loadGlyphRange = require('../style/load_glyph_range');
|
|
2
|
+
|
|
3
|
+
const TinySDF = require('@mapbox/tiny-sdf');
|
|
4
|
+
const isChar = require('../util/is_char_in_unicode_block');
|
|
5
|
+
const { AlphaImage } = require('../util/image');
|
|
6
|
+
const { callback } = require('../util/callback');
|
|
7
|
+
|
|
8
|
+
class GlyphManager {
|
|
9
|
+
// exposed as statics to enable stubbing in unit tests
|
|
10
|
+
static loadGlyphRange = loadGlyphRange;
|
|
11
|
+
static TinySDF = TinySDF;
|
|
12
|
+
|
|
13
|
+
constructor(localIdeographFontFamily) {
|
|
14
|
+
this.localIdeographFontFamily = localIdeographFontFamily;
|
|
15
|
+
this.entries = {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setGlyphsLoader(loader) {
|
|
19
|
+
this.loader = loader;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getGlyphs(glyphs, fn) {
|
|
23
|
+
return callback(fn, perform.call(this, glyphs));
|
|
24
|
+
|
|
25
|
+
async function perform(glyphs) {
|
|
26
|
+
const all = [];
|
|
27
|
+
for (const stack in glyphs) {
|
|
28
|
+
for (const id of glyphs[stack]) {
|
|
29
|
+
all.push(retrieveGlyph(this, { stack, id }));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const fetchedGlyphs = await Promise.all(all);
|
|
33
|
+
const result = {};
|
|
34
|
+
for (const { stack, id, glyph } of fetchedGlyphs) {
|
|
35
|
+
// Clone the glyph so that our own copy of its ArrayBuffer doesn't get transferred.
|
|
36
|
+
(result[stack] ??= {})[id] = cloneGlyph(glyph);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
|
|
40
|
+
function cloneGlyph(glyph) {
|
|
41
|
+
if (glyph) {
|
|
42
|
+
return {
|
|
43
|
+
id: glyph.id,
|
|
44
|
+
bitmap: glyph.bitmap.clone(),
|
|
45
|
+
metrics: glyph.metrics
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function retrieveGlyph({ entries, loader, localIdeographFontFamily }, { stack, id }) {
|
|
51
|
+
const entry = (entries[stack] ??= { glyphs: {}, requests: {} });
|
|
52
|
+
|
|
53
|
+
let glyph = entry.glyphs[id];
|
|
54
|
+
if (glyph) {
|
|
55
|
+
return { stack, id, glyph };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
glyph = tinySDF(localIdeographFontFamily, entry, stack, id);
|
|
59
|
+
if (glyph) {
|
|
60
|
+
return { stack, id, glyph };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const range = Math.floor(id / 256);
|
|
64
|
+
if (range * 256 > 65535) {
|
|
65
|
+
throw new Error('glyphs > 65535 not supported');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const promise = (entry.requests[range] ??= GlyphManager.loadGlyphRange(stack, range, loader));
|
|
69
|
+
const response = await promise;
|
|
70
|
+
if (response) {
|
|
71
|
+
for (const id in response) {
|
|
72
|
+
entry.glyphs[+id] = response[+id];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
delete entry.requests[range];
|
|
76
|
+
return { stack, id, glyph: response?.[id] || null };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = GlyphManager;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Creates a glyph descriptor for a character using TinySDF if the character belongs to
|
|
86
|
+
* the CJK Unified Ideographs or Hangul Syllables ranges.
|
|
87
|
+
*
|
|
88
|
+
* The function checks if the provided font family is valid and whether the Unicode code
|
|
89
|
+
* point (id) falls within the supported character ranges. If so, it creates or reuses a
|
|
90
|
+
* TinySDF instance from the given entry to generate a bitmap for the character.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} family - The font family to be used for rendering the glyph.
|
|
93
|
+
* @param {Object} entry - An object containing glyph-related data. May store a cached TinySDF instance.
|
|
94
|
+
* @param {string} stack - A string representing the font style stack (e.g., "bold", "medium", "light") to determine the font weight.
|
|
95
|
+
* @param {number} id - The Unicode code point of the character to render.
|
|
96
|
+
* @returns {Object|undefined} An object with the glyph descriptor containing:
|
|
97
|
+
* - id {number}: The Unicode code point.
|
|
98
|
+
* - bitmap {AlphaImage}: An image instance created from the glyph bitmap.
|
|
99
|
+
* - metrics {Object}: An object containing rendering metrics:
|
|
100
|
+
* - width {number}: The width of the glyph.
|
|
101
|
+
* - height {number}: The height of the glyph.
|
|
102
|
+
* - left {number}: The left bearing for the glyph.
|
|
103
|
+
* - top {number}: The top bearing for the glyph (used for vertical offset).
|
|
104
|
+
* - advance {number}: The advance width for spacing the glyph.
|
|
105
|
+
*
|
|
106
|
+
* Returns undefined if no font family is provided or if the character is not within the supported ranges.
|
|
107
|
+
*/
|
|
108
|
+
function tinySDF(family, entry, stack, id) {
|
|
109
|
+
if (!family) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!isChar['CJK Unified Ideographs'](id) && !isChar['Hangul Syllables'](id)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const tinySDF = getTinySDF();
|
|
118
|
+
return {
|
|
119
|
+
id,
|
|
120
|
+
bitmap: new AlphaImage({ width: 30, height: 30 }, tinySDF.draw(String.fromCharCode(id))),
|
|
121
|
+
metrics: {
|
|
122
|
+
width: 24,
|
|
123
|
+
height: 24,
|
|
124
|
+
left: 0,
|
|
125
|
+
top: -8,
|
|
126
|
+
advance: 24
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
function getTinySDF() {
|
|
131
|
+
const { tinySDF } = entry;
|
|
132
|
+
if (tinySDF) {
|
|
133
|
+
return tinySDF;
|
|
134
|
+
}
|
|
135
|
+
let fontWeight = '400';
|
|
136
|
+
if (/bold/i.test(stack)) {
|
|
137
|
+
fontWeight = '900';
|
|
138
|
+
} else if (/medium/i.test(stack)) {
|
|
139
|
+
fontWeight = '500';
|
|
140
|
+
} else if (/light/i.test(stack)) {
|
|
141
|
+
fontWeight = '200';
|
|
142
|
+
}
|
|
143
|
+
return (entry.tinySDF = new GlyphManager.TinySDF(24, 3, 8, 0.25, family, fontWeight));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const ShelfPack = require('@mapbox/shelf-pack');
|
|
2
|
+
|
|
3
|
+
const { RGBAImage } = require('../util/image');
|
|
4
|
+
const { register } = require('../util/web_worker_transfer');
|
|
5
|
+
|
|
6
|
+
const padding = 1;
|
|
7
|
+
|
|
8
|
+
class ImagePosition {
|
|
9
|
+
constructor(paddedRect, { pixelRatio }) {
|
|
10
|
+
this.paddedRect = paddedRect;
|
|
11
|
+
this.pixelRatio = pixelRatio;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get tl() {
|
|
15
|
+
return [this.paddedRect.x + padding, this.paddedRect.y + padding];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get br() {
|
|
19
|
+
return [this.paddedRect.x + this.paddedRect.w - padding, this.paddedRect.y + this.paddedRect.h - padding];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get tlbr() {
|
|
23
|
+
return this.tl.concat(this.br);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get displaySize() {
|
|
27
|
+
return [(this.paddedRect.w - padding * 2) / this.pixelRatio, (this.paddedRect.h - padding * 2) / this.pixelRatio];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class ImageAtlas {
|
|
32
|
+
constructor(icons, patterns) {
|
|
33
|
+
const iconPositions = {};
|
|
34
|
+
const patternPositions = {};
|
|
35
|
+
const pack = new ShelfPack(0, 0, { autoResize: true });
|
|
36
|
+
const bins = [];
|
|
37
|
+
for (const id in icons) {
|
|
38
|
+
const src = icons[id];
|
|
39
|
+
const bin = {
|
|
40
|
+
x: 0,
|
|
41
|
+
y: 0,
|
|
42
|
+
w: src.data.width + 2 * padding,
|
|
43
|
+
h: src.data.height + 2 * padding
|
|
44
|
+
};
|
|
45
|
+
bins.push(bin);
|
|
46
|
+
iconPositions[id] = new ImagePosition(bin, src);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
for (const id in patterns) {
|
|
50
|
+
const src = patterns[id];
|
|
51
|
+
const bin = {
|
|
52
|
+
x: 0,
|
|
53
|
+
y: 0,
|
|
54
|
+
w: src.data.width + 2 * padding,
|
|
55
|
+
h: src.data.height + 2 * padding
|
|
56
|
+
};
|
|
57
|
+
bins.push(bin);
|
|
58
|
+
patternPositions[id] = new ImagePosition(bin, src);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pack.pack(bins, { inPlace: true });
|
|
62
|
+
|
|
63
|
+
const image = new RGBAImage({ width: pack.w, height: pack.h });
|
|
64
|
+
|
|
65
|
+
for (const id in icons) {
|
|
66
|
+
const src = icons[id];
|
|
67
|
+
const bin = iconPositions[id].paddedRect;
|
|
68
|
+
RGBAImage.copy(src.data, image, { x: 0, y: 0 }, { x: bin.x + padding, y: bin.y + padding }, src.data);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (const id in patterns) {
|
|
72
|
+
const src = patterns[id];
|
|
73
|
+
const bin = patternPositions[id].paddedRect;
|
|
74
|
+
const x = bin.x + padding;
|
|
75
|
+
const y = bin.y + padding;
|
|
76
|
+
const w = src.data.width;
|
|
77
|
+
const h = src.data.height;
|
|
78
|
+
|
|
79
|
+
RGBAImage.copy(src.data, image, { x: 0, y: 0 }, { x: x, y: y }, src.data);
|
|
80
|
+
// Add 1 pixel wrapped padding on each side of the image.
|
|
81
|
+
RGBAImage.copy(src.data, image, { x: 0, y: h - 1 }, { x: x, y: y - 1 }, { width: w, height: 1 }); // T
|
|
82
|
+
RGBAImage.copy(src.data, image, { x: 0, y: 0 }, { x: x, y: y + h }, { width: w, height: 1 }); // B
|
|
83
|
+
RGBAImage.copy(src.data, image, { x: w - 1, y: 0 }, { x: x - 1, y: y }, { width: 1, height: h }); // L
|
|
84
|
+
RGBAImage.copy(src.data, image, { x: 0, y: 0 }, { x: x + w, y: y }, { width: 1, height: h }); // R
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.image = image;
|
|
88
|
+
this.iconPositions = iconPositions;
|
|
89
|
+
this.patternPositions = patternPositions;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
ImageAtlas.ImagePosition = ImagePosition;
|
|
94
|
+
module.exports = ImageAtlas;
|
|
95
|
+
|
|
96
|
+
register('ImagePosition', ImagePosition);
|
|
97
|
+
register('ImageAtlas', ImageAtlas);
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const ShelfPack = require('@mapbox/shelf-pack');
|
|
2
|
+
|
|
3
|
+
const { RGBAImage } = require('../util/image');
|
|
4
|
+
const { ImagePosition } = require('./image_atlas');
|
|
5
|
+
const Texture = require('./texture');
|
|
6
|
+
const assert = require('assert');
|
|
7
|
+
|
|
8
|
+
// When copied into the atlas texture, image data is padded by one pixel on each side. Icon
|
|
9
|
+
// images are padded with fully transparent pixels, while pattern images are padded with a
|
|
10
|
+
// copy of the image data wrapped from the opposite side. In both cases, this ensures the
|
|
11
|
+
// correct behavior of GL_LINEAR texture sampling mode.
|
|
12
|
+
const padding = 1;
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
ImageManager does two things:
|
|
16
|
+
|
|
17
|
+
1. Tracks requests for icon images from tile workers and sends responses when the requests are fulfilled.
|
|
18
|
+
2. Builds a texture atlas for pattern images.
|
|
19
|
+
|
|
20
|
+
These are disparate responsibilities and should eventually be handled by different classes. When we implement
|
|
21
|
+
data-driven support for `*-pattern`, we'll likely use per-bucket pattern atlases, and that would be a good time
|
|
22
|
+
to refactor this.
|
|
23
|
+
*/
|
|
24
|
+
class ImageManager {
|
|
25
|
+
constructor() {
|
|
26
|
+
this.images = {};
|
|
27
|
+
this.loaded = false;
|
|
28
|
+
this.requestors = [];
|
|
29
|
+
|
|
30
|
+
this.shelfPack = new ShelfPack(64, 64, { autoResize: true });
|
|
31
|
+
this.patterns = {};
|
|
32
|
+
this.atlasImage = new RGBAImage({ width: 64, height: 64 });
|
|
33
|
+
this.dirty = true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
isLoaded() {
|
|
37
|
+
return this.loaded;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setLoaded(loaded) {
|
|
41
|
+
if (this.loaded === loaded) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.loaded = loaded;
|
|
46
|
+
|
|
47
|
+
if (loaded) {
|
|
48
|
+
for (const { ids, callback } of this.requestors) {
|
|
49
|
+
this._notify(ids, callback);
|
|
50
|
+
}
|
|
51
|
+
this.requestors = [];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getImage(id) {
|
|
56
|
+
return this.images[id];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
addImage(id, image) {
|
|
60
|
+
assert(!this.images[id]);
|
|
61
|
+
this.images[id] = image;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
removeImage(id) {
|
|
65
|
+
assert(this.images[id]);
|
|
66
|
+
delete this.images[id];
|
|
67
|
+
|
|
68
|
+
const pattern = this.patterns[id];
|
|
69
|
+
if (pattern) {
|
|
70
|
+
this.shelfPack.unref(pattern.bin);
|
|
71
|
+
delete this.patterns[id];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
listImages() {
|
|
76
|
+
return Object.keys(this.images);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getImages(ids, callback) {
|
|
80
|
+
// If the sprite has been loaded, or if all the icon dependencies are already present
|
|
81
|
+
// (i.e. if they've been addeded via runtime styling), then notify the requestor immediately.
|
|
82
|
+
// Otherwise, delay notification until the sprite is loaded. At that point, if any of the
|
|
83
|
+
// dependencies are still unavailable, we'll just assume they are permanently missing.
|
|
84
|
+
let hasAllDependencies = true;
|
|
85
|
+
if (!this.isLoaded()) {
|
|
86
|
+
for (const id of ids) {
|
|
87
|
+
if (!this.images[id]) {
|
|
88
|
+
hasAllDependencies = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (this.isLoaded() || hasAllDependencies) {
|
|
93
|
+
this._notify(ids, callback);
|
|
94
|
+
} else {
|
|
95
|
+
this.requestors.push({ ids, callback });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_notify(ids, callback) {
|
|
100
|
+
const response = {};
|
|
101
|
+
|
|
102
|
+
for (const id of ids) {
|
|
103
|
+
const image = this.images[id];
|
|
104
|
+
if (image) {
|
|
105
|
+
// Clone the image so that our own copy of its ArrayBuffer doesn't get transferred.
|
|
106
|
+
response[id] = {
|
|
107
|
+
data: image.data.clone(),
|
|
108
|
+
pixelRatio: image.pixelRatio,
|
|
109
|
+
sdf: image.sdf
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
callback(null, response);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Pattern stuff
|
|
118
|
+
|
|
119
|
+
getPixelSize() {
|
|
120
|
+
return {
|
|
121
|
+
width: this.shelfPack.w,
|
|
122
|
+
height: this.shelfPack.h
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
getPattern(id) {
|
|
127
|
+
const pattern = this.patterns[id];
|
|
128
|
+
if (pattern) {
|
|
129
|
+
return pattern.position;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const image = this.getImage(id);
|
|
133
|
+
if (!image) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const width = image.data.width + padding * 2;
|
|
138
|
+
const height = image.data.height + padding * 2;
|
|
139
|
+
|
|
140
|
+
const bin = this.shelfPack.packOne(width, height);
|
|
141
|
+
if (!bin) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.atlasImage.resize(this.getPixelSize());
|
|
146
|
+
|
|
147
|
+
const src = image.data;
|
|
148
|
+
const dst = this.atlasImage;
|
|
149
|
+
|
|
150
|
+
const x = bin.x + padding;
|
|
151
|
+
const y = bin.y + padding;
|
|
152
|
+
const w = src.width;
|
|
153
|
+
const h = src.height;
|
|
154
|
+
|
|
155
|
+
RGBAImage.copy(src, dst, { x: 0, y: 0 }, { x, y }, { width: w, height: h });
|
|
156
|
+
|
|
157
|
+
// Add 1 pixel wrapped padding on each side of the image.
|
|
158
|
+
RGBAImage.copy(src, dst, { x: 0, y: h - 1 }, { x: x, y: y - 1 }, { width: w, height: 1 }); // T
|
|
159
|
+
RGBAImage.copy(src, dst, { x: 0, y: 0 }, { x: x, y: y + h }, { width: w, height: 1 }); // B
|
|
160
|
+
RGBAImage.copy(src, dst, { x: w - 1, y: 0 }, { x: x - 1, y: y }, { width: 1, height: h }); // L
|
|
161
|
+
RGBAImage.copy(src, dst, { x: 0, y: 0 }, { x: x + w, y: y }, { width: 1, height: h }); // R
|
|
162
|
+
|
|
163
|
+
this.dirty = true;
|
|
164
|
+
|
|
165
|
+
const position = new ImagePosition(bin, image);
|
|
166
|
+
this.patterns[id] = { bin, position };
|
|
167
|
+
return position;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
bind(context) {
|
|
171
|
+
const gl = context.gl;
|
|
172
|
+
if (!this.atlasTexture) {
|
|
173
|
+
this.atlasTexture = new Texture(context, this.atlasImage, gl.RGBA);
|
|
174
|
+
} else if (this.dirty) {
|
|
175
|
+
this.atlasTexture.update(this.atlasImage);
|
|
176
|
+
this.dirty = false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.atlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
module.exports = ImageManager;
|