@scoova/mgl 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. package/LICENSE.txt +116 -0
  2. package/README.md +174 -0
  3. package/build/banner.ts +12 -0
  4. package/build/bump-version-changelog.js +26 -0
  5. package/build/check-bundle-size.js +77 -0
  6. package/build/generate-dist-package.js +26 -0
  7. package/build/generate-doc-images.ts +78 -0
  8. package/build/generate-docs.ts +190 -0
  9. package/build/generate-shaders.ts +68 -0
  10. package/build/generate-struct-arrays.ts +438 -0
  11. package/build/generate-style-code.ts +283 -0
  12. package/build/readme.md +56 -0
  13. package/build/release-notes.js +45 -0
  14. package/build/rollup/bundle_prelude.js +29 -0
  15. package/build/rollup/maplibregl.js +22 -0
  16. package/build/rollup_plugins.ts +58 -0
  17. package/dist/LICENSE.txt +116 -0
  18. package/dist/maplibre-gl.css +1 -0
  19. package/dist/maplibre-gl.d.ts +13304 -0
  20. package/dist/maplibre-gl.js +59 -0
  21. package/dist/maplibre-gl.js.map +1 -0
  22. package/dist/package.json +1 -0
  23. package/package.json +192 -0
  24. package/src/css/maplibre-gl.css +854 -0
  25. package/src/css/svg/maplibregl-ctrl-attrib.svg +3 -0
  26. package/src/css/svg/maplibregl-ctrl-compass.svg +4 -0
  27. package/src/css/svg/maplibregl-ctrl-fullscreen.svg +3 -0
  28. package/src/css/svg/maplibregl-ctrl-geolocate.svg +5 -0
  29. package/src/css/svg/maplibregl-ctrl-logo.svg +11 -0
  30. package/src/css/svg/maplibregl-ctrl-shrink.svg +3 -0
  31. package/src/css/svg/maplibregl-ctrl-terrain.svg +3 -0
  32. package/src/css/svg/maplibregl-ctrl-zoom-in.svg +3 -0
  33. package/src/css/svg/maplibregl-ctrl-zoom-out.svg +3 -0
  34. package/src/data/array_types.g.ts +1130 -0
  35. package/src/data/bucket/circle_attributes.ts +8 -0
  36. package/src/data/bucket/circle_bucket.ts +197 -0
  37. package/src/data/bucket/fill_attributes.ts +8 -0
  38. package/src/data/bucket/fill_bucket.test.ts +95 -0
  39. package/src/data/bucket/fill_bucket.ts +228 -0
  40. package/src/data/bucket/fill_extrusion_attributes.ts +13 -0
  41. package/src/data/bucket/fill_extrusion_bucket.ts +305 -0
  42. package/src/data/bucket/heatmap_bucket.ts +12 -0
  43. package/src/data/bucket/line_attributes.ts +8 -0
  44. package/src/data/bucket/line_attributes_ext.ts +8 -0
  45. package/src/data/bucket/line_bucket.test.ts +142 -0
  46. package/src/data/bucket/line_bucket.ts +592 -0
  47. package/src/data/bucket/pattern_attributes.ts +9 -0
  48. package/src/data/bucket/pattern_bucket_features.ts +57 -0
  49. package/src/data/bucket/symbol_attributes.ts +122 -0
  50. package/src/data/bucket/symbol_bucket.test.ts +243 -0
  51. package/src/data/bucket/symbol_bucket.ts +975 -0
  52. package/src/data/bucket.ts +123 -0
  53. package/src/data/dem_data.test.ts +237 -0
  54. package/src/data/dem_data.ts +171 -0
  55. package/src/data/evaluation_feature.ts +18 -0
  56. package/src/data/extent.ts +13 -0
  57. package/src/data/feature_index.ts +337 -0
  58. package/src/data/feature_position_map.test.ts +33 -0
  59. package/src/data/feature_position_map.ts +126 -0
  60. package/src/data/index_array_type.ts +9 -0
  61. package/src/data/load_geometry.test.ts +49 -0
  62. package/src/data/load_geometry.ts +44 -0
  63. package/src/data/pos3d_attributes.ts +5 -0
  64. package/src/data/pos_attributes.ts +5 -0
  65. package/src/data/program_configuration.ts +735 -0
  66. package/src/data/raster_bounds_attributes.ts +6 -0
  67. package/src/data/segment.ts +89 -0
  68. package/src/geo/edge_insets.test.ts +83 -0
  69. package/src/geo/edge_insets.ts +146 -0
  70. package/src/geo/lng_lat.test.ts +65 -0
  71. package/src/geo/lng_lat.ts +169 -0
  72. package/src/geo/lng_lat_bounds.test.ts +357 -0
  73. package/src/geo/lng_lat_bounds.ts +356 -0
  74. package/src/geo/mercator_coordinate.test.ts +34 -0
  75. package/src/geo/mercator_coordinate.ts +157 -0
  76. package/src/geo/projection/projection.ts +72 -0
  77. package/src/geo/transform.test.ts +509 -0
  78. package/src/geo/transform.ts +1072 -0
  79. package/src/gl/color_mode.ts +31 -0
  80. package/src/gl/context.ts +321 -0
  81. package/src/gl/cull_face_mode.ts +22 -0
  82. package/src/gl/depth_mode.ts +26 -0
  83. package/src/gl/framebuffer.ts +48 -0
  84. package/src/gl/index_buffer.ts +55 -0
  85. package/src/gl/render_pool.test.ts +69 -0
  86. package/src/gl/render_pool.ts +93 -0
  87. package/src/gl/state.test.ts +125 -0
  88. package/src/gl/stencil_mode.ts +27 -0
  89. package/src/gl/types.ts +59 -0
  90. package/src/gl/value.ts +534 -0
  91. package/src/gl/vertex_buffer.test.ts +57 -0
  92. package/src/gl/vertex_buffer.ts +111 -0
  93. package/src/gl/webgl2.ts +12 -0
  94. package/src/index.test.ts +121 -0
  95. package/src/index.ts +250 -0
  96. package/src/render/draw_background.ts +53 -0
  97. package/src/render/draw_circle.ts +113 -0
  98. package/src/render/draw_collision_debug.ts +168 -0
  99. package/src/render/draw_custom.test.ts +73 -0
  100. package/src/render/draw_custom.ts +45 -0
  101. package/src/render/draw_debug.test.ts +122 -0
  102. package/src/render/draw_debug.ts +148 -0
  103. package/src/render/draw_fill.test.ts +137 -0
  104. package/src/render/draw_fill.ts +128 -0
  105. package/src/render/draw_fill_extrusion.ts +97 -0
  106. package/src/render/draw_heatmap.ts +228 -0
  107. package/src/render/draw_hillshade.ts +119 -0
  108. package/src/render/draw_line.ts +125 -0
  109. package/src/render/draw_raster.ts +133 -0
  110. package/src/render/draw_sky.ts +44 -0
  111. package/src/render/draw_symbol.test.ts +223 -0
  112. package/src/render/draw_symbol.ts +499 -0
  113. package/src/render/draw_terrain.ts +99 -0
  114. package/src/render/glyph_atlas.ts +83 -0
  115. package/src/render/glyph_manager.test.ts +147 -0
  116. package/src/render/glyph_manager.ts +198 -0
  117. package/src/render/image_atlas.ts +159 -0
  118. package/src/render/image_manager.ts +337 -0
  119. package/src/render/line_atlas.test.ts +38 -0
  120. package/src/render/line_atlas.ts +214 -0
  121. package/src/render/mesh.ts +25 -0
  122. package/src/render/painter.test.ts +51 -0
  123. package/src/render/painter.ts +666 -0
  124. package/src/render/program/background_program.ts +100 -0
  125. package/src/render/program/circle_program.ts +61 -0
  126. package/src/render/program/clipping_mask_program.ts +19 -0
  127. package/src/render/program/collision_program.ts +47 -0
  128. package/src/render/program/debug_program.ts +29 -0
  129. package/src/render/program/fill_extrusion_program.ts +120 -0
  130. package/src/render/program/fill_program.ts +121 -0
  131. package/src/render/program/heatmap_program.ts +76 -0
  132. package/src/render/program/hillshade_program.ts +116 -0
  133. package/src/render/program/line_program.ts +207 -0
  134. package/src/render/program/pattern.ts +102 -0
  135. package/src/render/program/program_uniforms.ts +46 -0
  136. package/src/render/program/raster_program.ts +88 -0
  137. package/src/render/program/sky_program.ts +28 -0
  138. package/src/render/program/symbol_program.ts +266 -0
  139. package/src/render/program/terrain_program.ts +116 -0
  140. package/src/render/program.ts +233 -0
  141. package/src/render/render_to_texture.test.ts +151 -0
  142. package/src/render/render_to_texture.ts +197 -0
  143. package/src/render/terrain.test.ts +322 -0
  144. package/src/render/terrain.ts +464 -0
  145. package/src/render/texture.ts +114 -0
  146. package/src/render/uniform_binding.test.ts +122 -0
  147. package/src/render/uniform_binding.ts +157 -0
  148. package/src/render/update_pattern_positions_in_program.test.ts +74 -0
  149. package/src/render/update_pattern_positions_in_program.ts +50 -0
  150. package/src/render/vertex_array_object.ts +163 -0
  151. package/src/shaders/README.md +42 -0
  152. package/src/shaders/_prelude.fragment.glsl +19 -0
  153. package/src/shaders/_prelude.fragment.glsl.g.ts +2 -0
  154. package/src/shaders/_prelude.vertex.glsl +148 -0
  155. package/src/shaders/_prelude.vertex.glsl.g.ts +2 -0
  156. package/src/shaders/background.fragment.glsl +10 -0
  157. package/src/shaders/background.fragment.glsl.g.ts +2 -0
  158. package/src/shaders/background.vertex.glsl +7 -0
  159. package/src/shaders/background.vertex.glsl.g.ts +2 -0
  160. package/src/shaders/background_pattern.fragment.glsl +28 -0
  161. package/src/shaders/background_pattern.fragment.glsl.g.ts +2 -0
  162. package/src/shaders/background_pattern.vertex.glsl +19 -0
  163. package/src/shaders/background_pattern.vertex.glsl.g.ts +2 -0
  164. package/src/shaders/circle.fragment.glsl +34 -0
  165. package/src/shaders/circle.fragment.glsl.g.ts +2 -0
  166. package/src/shaders/circle.vertex.glsl +68 -0
  167. package/src/shaders/circle.vertex.glsl.g.ts +2 -0
  168. package/src/shaders/clipping_mask.fragment.glsl +3 -0
  169. package/src/shaders/clipping_mask.fragment.glsl.g.ts +2 -0
  170. package/src/shaders/clipping_mask.vertex.glsl +7 -0
  171. package/src/shaders/clipping_mask.vertex.glsl.g.ts +2 -0
  172. package/src/shaders/collision_box.fragment.glsl +20 -0
  173. package/src/shaders/collision_box.fragment.glsl.g.ts +2 -0
  174. package/src/shaders/collision_box.vertex.glsl +27 -0
  175. package/src/shaders/collision_box.vertex.glsl.g.ts +2 -0
  176. package/src/shaders/collision_circle.fragment.glsl +17 -0
  177. package/src/shaders/collision_circle.fragment.glsl.g.ts +2 -0
  178. package/src/shaders/collision_circle.vertex.glsl +59 -0
  179. package/src/shaders/collision_circle.vertex.glsl.g.ts +2 -0
  180. package/src/shaders/debug.fragment.glsl +9 -0
  181. package/src/shaders/debug.fragment.glsl.g.ts +2 -0
  182. package/src/shaders/debug.vertex.glsl +12 -0
  183. package/src/shaders/debug.vertex.glsl.g.ts +2 -0
  184. package/src/shaders/encode_attribute.test.ts +11 -0
  185. package/src/shaders/encode_attribute.ts +13 -0
  186. package/src/shaders/fill.fragment.glsl +13 -0
  187. package/src/shaders/fill.fragment.glsl.g.ts +2 -0
  188. package/src/shaders/fill.vertex.glsl +13 -0
  189. package/src/shaders/fill.vertex.glsl.g.ts +2 -0
  190. package/src/shaders/fill_extrusion.fragment.glsl +9 -0
  191. package/src/shaders/fill_extrusion.fragment.glsl.g.ts +2 -0
  192. package/src/shaders/fill_extrusion.vertex.glsl +84 -0
  193. package/src/shaders/fill_extrusion.vertex.glsl.g.ts +2 -0
  194. package/src/shaders/fill_extrusion_pattern.fragment.glsl +47 -0
  195. package/src/shaders/fill_extrusion_pattern.fragment.glsl.g.ts +2 -0
  196. package/src/shaders/fill_extrusion_pattern.vertex.glsl +96 -0
  197. package/src/shaders/fill_extrusion_pattern.vertex.glsl.g.ts +2 -0
  198. package/src/shaders/fill_outline.fragment.glsl +17 -0
  199. package/src/shaders/fill_outline.fragment.glsl.g.ts +2 -0
  200. package/src/shaders/fill_outline.vertex.glsl +17 -0
  201. package/src/shaders/fill_outline.vertex.glsl.g.ts +2 -0
  202. package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
  203. package/src/shaders/fill_outline_pattern.fragment.glsl.g.ts +2 -0
  204. package/src/shaders/fill_outline_pattern.vertex.glsl +44 -0
  205. package/src/shaders/fill_outline_pattern.vertex.glsl.g.ts +2 -0
  206. package/src/shaders/fill_pattern.fragment.glsl +39 -0
  207. package/src/shaders/fill_pattern.fragment.glsl.g.ts +2 -0
  208. package/src/shaders/fill_pattern.vertex.glsl +39 -0
  209. package/src/shaders/fill_pattern.vertex.glsl.g.ts +2 -0
  210. package/src/shaders/heatmap.fragment.glsl +22 -0
  211. package/src/shaders/heatmap.fragment.glsl.g.ts +2 -0
  212. package/src/shaders/heatmap.vertex.glsl +54 -0
  213. package/src/shaders/heatmap.vertex.glsl.g.ts +2 -0
  214. package/src/shaders/heatmap_texture.fragment.glsl +15 -0
  215. package/src/shaders/heatmap_texture.fragment.glsl.g.ts +2 -0
  216. package/src/shaders/heatmap_texture.vertex.glsl +11 -0
  217. package/src/shaders/heatmap_texture.vertex.glsl.g.ts +2 -0
  218. package/src/shaders/hillshade.fragment.glsl +52 -0
  219. package/src/shaders/hillshade.fragment.glsl.g.ts +2 -0
  220. package/src/shaders/hillshade.vertex.glsl +11 -0
  221. package/src/shaders/hillshade.vertex.glsl.g.ts +2 -0
  222. package/src/shaders/hillshade_prepare.fragment.glsl +77 -0
  223. package/src/shaders/hillshade_prepare.fragment.glsl.g.ts +2 -0
  224. package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
  225. package/src/shaders/hillshade_prepare.vertex.glsl.g.ts +2 -0
  226. package/src/shaders/line.fragment.glsl +30 -0
  227. package/src/shaders/line.fragment.glsl.g.ts +2 -0
  228. package/src/shaders/line.vertex.glsl +89 -0
  229. package/src/shaders/line.vertex.glsl.g.ts +2 -0
  230. package/src/shaders/line_gradient.fragment.glsl +34 -0
  231. package/src/shaders/line_gradient.fragment.glsl.g.ts +2 -0
  232. package/src/shaders/line_gradient.vertex.glsl +92 -0
  233. package/src/shaders/line_gradient.vertex.glsl.g.ts +2 -0
  234. package/src/shaders/line_pattern.fragment.glsl +77 -0
  235. package/src/shaders/line_pattern.fragment.glsl.g.ts +2 -0
  236. package/src/shaders/line_pattern.vertex.glsl +103 -0
  237. package/src/shaders/line_pattern.vertex.glsl.g.ts +2 -0
  238. package/src/shaders/line_sdf.fragment.glsl +45 -0
  239. package/src/shaders/line_sdf.fragment.glsl.g.ts +2 -0
  240. package/src/shaders/line_sdf.vertex.glsl +101 -0
  241. package/src/shaders/line_sdf.vertex.glsl.g.ts +2 -0
  242. package/src/shaders/raster.fragment.glsl +53 -0
  243. package/src/shaders/raster.fragment.glsl.g.ts +2 -0
  244. package/src/shaders/raster.vertex.glsl +21 -0
  245. package/src/shaders/raster.vertex.glsl.g.ts +2 -0
  246. package/src/shaders/shaders.ts +197 -0
  247. package/src/shaders/sky.fragment.glsl +17 -0
  248. package/src/shaders/sky.fragment.glsl.g.ts +2 -0
  249. package/src/shaders/sky.vertex.glsl +5 -0
  250. package/src/shaders/sky.vertex.glsl.g.ts +2 -0
  251. package/src/shaders/symbol_icon.fragment.glsl +17 -0
  252. package/src/shaders/symbol_icon.fragment.glsl.g.ts +2 -0
  253. package/src/shaders/symbol_icon.vertex.glsl +117 -0
  254. package/src/shaders/symbol_icon.vertex.glsl.g.ts +2 -0
  255. package/src/shaders/symbol_sdf.fragment.glsl +58 -0
  256. package/src/shaders/symbol_sdf.fragment.glsl.g.ts +2 -0
  257. package/src/shaders/symbol_sdf.vertex.glsl +142 -0
  258. package/src/shaders/symbol_sdf.vertex.glsl.g.ts +2 -0
  259. package/src/shaders/symbol_text_and_icon.fragment.glsl +68 -0
  260. package/src/shaders/symbol_text_and_icon.fragment.glsl.g.ts +2 -0
  261. package/src/shaders/symbol_text_and_icon.vertex.glsl +140 -0
  262. package/src/shaders/symbol_text_and_icon.vertex.glsl.g.ts +2 -0
  263. package/src/shaders/terrain.fragment.glsl +32 -0
  264. package/src/shaders/terrain.fragment.glsl.g.ts +2 -0
  265. package/src/shaders/terrain.vertex.glsl +17 -0
  266. package/src/shaders/terrain.vertex.glsl.g.ts +2 -0
  267. package/src/shaders/terrain_coords.fragment.glsl +11 -0
  268. package/src/shaders/terrain_coords.fragment.glsl.g.ts +2 -0
  269. package/src/shaders/terrain_coords.vertex.glsl +13 -0
  270. package/src/shaders/terrain_coords.vertex.glsl.g.ts +2 -0
  271. package/src/shaders/terrain_depth.fragment.glsl +15 -0
  272. package/src/shaders/terrain_depth.fragment.glsl.g.ts +2 -0
  273. package/src/shaders/terrain_depth.vertex.glsl +13 -0
  274. package/src/shaders/terrain_depth.vertex.glsl.g.ts +2 -0
  275. package/src/source/canvas_source.test.ts +210 -0
  276. package/src/source/canvas_source.ts +227 -0
  277. package/src/source/geojson_source.test.ts +492 -0
  278. package/src/source/geojson_source.ts +431 -0
  279. package/src/source/geojson_source_diff.test.ts +364 -0
  280. package/src/source/geojson_source_diff.ts +172 -0
  281. package/src/source/geojson_worker_source.test.ts +399 -0
  282. package/src/source/geojson_worker_source.ts +303 -0
  283. package/src/source/geojson_wrapper.test.ts +32 -0
  284. package/src/source/geojson_wrapper.ts +81 -0
  285. package/src/source/image_source.test.ts +235 -0
  286. package/src/source/image_source.ts +338 -0
  287. package/src/source/load_tilejson.ts +47 -0
  288. package/src/source/pixels_to_tile_units.ts +25 -0
  289. package/src/source/protocol_crud.ts +48 -0
  290. package/src/source/query_features.test.ts +31 -0
  291. package/src/source/query_features.ts +252 -0
  292. package/src/source/raster_dem_tile_source.test.ts +158 -0
  293. package/src/source/raster_dem_tile_source.ts +166 -0
  294. package/src/source/raster_dem_tile_worker_source.test.ts +36 -0
  295. package/src/source/raster_dem_tile_worker_source.ts +38 -0
  296. package/src/source/raster_tile_source.test.ts +206 -0
  297. package/src/source/raster_tile_source.ts +227 -0
  298. package/src/source/rtl_text_plugin_main_thread.test.ts +170 -0
  299. package/src/source/rtl_text_plugin_main_thread.ts +89 -0
  300. package/src/source/rtl_text_plugin_status.ts +33 -0
  301. package/src/source/rtl_text_plugin_worker.ts +49 -0
  302. package/src/source/source.test.ts +41 -0
  303. package/src/source/source.ts +186 -0
  304. package/src/source/source_cache.test.ts +2069 -0
  305. package/src/source/source_cache.ts +1102 -0
  306. package/src/source/source_state.ts +157 -0
  307. package/src/source/terrain_source_cache.test.ts +105 -0
  308. package/src/source/terrain_source_cache.ts +204 -0
  309. package/src/source/tile.test.ts +290 -0
  310. package/src/source/tile.ts +478 -0
  311. package/src/source/tile_bounds.ts +34 -0
  312. package/src/source/tile_cache.test.ts +130 -0
  313. package/src/source/tile_cache.ts +208 -0
  314. package/src/source/tile_id.test.ts +112 -0
  315. package/src/source/tile_id.ts +221 -0
  316. package/src/source/vector_tile_source.test.ts +401 -0
  317. package/src/source/vector_tile_source.ts +283 -0
  318. package/src/source/vector_tile_worker_source.test.ts +396 -0
  319. package/src/source/vector_tile_worker_source.ts +199 -0
  320. package/src/source/video_source.test.ts +124 -0
  321. package/src/source/video_source.ts +204 -0
  322. package/src/source/worker.test.ts +233 -0
  323. package/src/source/worker.ts +301 -0
  324. package/src/source/worker_source.ts +117 -0
  325. package/src/source/worker_tile.test.ts +226 -0
  326. package/src/source/worker_tile.ts +208 -0
  327. package/src/style/create_style_layer.ts +39 -0
  328. package/src/style/evaluation_parameters.ts +62 -0
  329. package/src/style/format_section_override.test.ts +62 -0
  330. package/src/style/format_section_override.ts +50 -0
  331. package/src/style/light.test.ts +86 -0
  332. package/src/style/light.ts +135 -0
  333. package/src/style/load_glyph_range.test.ts +40 -0
  334. package/src/style/load_glyph_range.ts +32 -0
  335. package/src/style/load_sprite.test.ts +227 -0
  336. package/src/style/load_sprite.ts +71 -0
  337. package/src/style/parse_glyph_pbf.ts +42 -0
  338. package/src/style/pauseable_placement.ts +138 -0
  339. package/src/style/properties.ts +726 -0
  340. package/src/style/query_utils.test.ts +107 -0
  341. package/src/style/query_utils.ts +70 -0
  342. package/src/style/sky.ts +127 -0
  343. package/src/style/style.test.ts +2654 -0
  344. package/src/style/style.ts +1814 -0
  345. package/src/style/style_glyph.ts +25 -0
  346. package/src/style/style_image.ts +188 -0
  347. package/src/style/style_layer/background_style_layer.ts +17 -0
  348. package/src/style/style_layer/background_style_layer_properties.g.ts +40 -0
  349. package/src/style/style_layer/circle_style_layer.ts +98 -0
  350. package/src/style/style_layer/circle_style_layer_properties.g.ts +76 -0
  351. package/src/style/style_layer/custom_style_layer.ts +233 -0
  352. package/src/style/style_layer/fill_extrusion_style_layer.ts +224 -0
  353. package/src/style/style_layer/fill_extrusion_style_layer_properties.g.ts +55 -0
  354. package/src/style/style_layer/fill_style_layer.test.ts +37 -0
  355. package/src/style/style_layer/fill_style_layer.ts +65 -0
  356. package/src/style/style_layer/fill_style_layer_properties.g.ts +64 -0
  357. package/src/style/style_layer/heatmap_style_layer.ts +74 -0
  358. package/src/style/style_layer/heatmap_style_layer_properties.g.ts +46 -0
  359. package/src/style/style_layer/hillshade_style_layer.ts +21 -0
  360. package/src/style/style_layer/hillshade_style_layer_properties.g.ts +49 -0
  361. package/src/style/style_layer/line_style_layer.test.ts +50 -0
  362. package/src/style/style_layer/line_style_layer.ts +131 -0
  363. package/src/style/style_layer/line_style_layer_properties.g.ts +88 -0
  364. package/src/style/style_layer/overlap_mode.test.ts +57 -0
  365. package/src/style/style_layer/overlap_mode.ts +25 -0
  366. package/src/style/style_layer/raster_style_layer.ts +17 -0
  367. package/src/style/style_layer/raster_style_layer_properties.g.ts +55 -0
  368. package/src/style/style_layer/symbol_style_layer.ts +195 -0
  369. package/src/style/style_layer/symbol_style_layer_properties.g.ts +218 -0
  370. package/src/style/style_layer/typed_style_layer.ts +9 -0
  371. package/src/style/style_layer/variable_text_anchor.test.ts +117 -0
  372. package/src/style/style_layer/variable_text_anchor.ts +163 -0
  373. package/src/style/style_layer.test.ts +372 -0
  374. package/src/style/style_layer.ts +287 -0
  375. package/src/style/style_layer_index.test.ts +99 -0
  376. package/src/style/style_layer_index.ts +78 -0
  377. package/src/style/validate_style.ts +53 -0
  378. package/src/style/zoom_history.ts +40 -0
  379. package/src/symbol/anchor.test.ts +14 -0
  380. package/src/symbol/anchor.ts +22 -0
  381. package/src/symbol/check_max_angle.test.ts +54 -0
  382. package/src/symbol/check_max_angle.ts +76 -0
  383. package/src/symbol/clip_line.test.ts +154 -0
  384. package/src/symbol/clip_line.ts +66 -0
  385. package/src/symbol/collision_feature.test.ts +98 -0
  386. package/src/symbol/collision_feature.ts +114 -0
  387. package/src/symbol/collision_index.test.ts +19 -0
  388. package/src/symbol/collision_index.ts +618 -0
  389. package/src/symbol/cross_tile_symbol_index.test.ts +260 -0
  390. package/src/symbol/cross_tile_symbol_index.ts +367 -0
  391. package/src/symbol/get_anchors.test.ts +113 -0
  392. package/src/symbol/get_anchors.ts +167 -0
  393. package/src/symbol/grid_index.test.ts +75 -0
  394. package/src/symbol/grid_index.ts +414 -0
  395. package/src/symbol/merge_lines.test.ts +30 -0
  396. package/src/symbol/merge_lines.ts +80 -0
  397. package/src/symbol/one_em.ts +3 -0
  398. package/src/symbol/opacity_state.ts +23 -0
  399. package/src/symbol/path_interpolator.test.ts +134 -0
  400. package/src/symbol/path_interpolator.ts +55 -0
  401. package/src/symbol/placement.ts +1371 -0
  402. package/src/symbol/projection.test.ts +171 -0
  403. package/src/symbol/projection.ts +833 -0
  404. package/src/symbol/quads.test.ts +157 -0
  405. package/src/symbol/quads.ts +349 -0
  406. package/src/symbol/shaping.test.ts +360 -0
  407. package/src/symbol/shaping.ts +911 -0
  408. package/src/symbol/symbol_layout.ts +739 -0
  409. package/src/symbol/symbol_size.ts +129 -0
  410. package/src/symbol/symbol_style_layer.test.ts +103 -0
  411. package/src/symbol/transform_text.ts +27 -0
  412. package/src/ui/anchor.ts +27 -0
  413. package/src/ui/camera.test.ts +2301 -0
  414. package/src/ui/camera.ts +1520 -0
  415. package/src/ui/control/attribution_control.test.ts +543 -0
  416. package/src/ui/control/attribution_control.ts +209 -0
  417. package/src/ui/control/control.ts +67 -0
  418. package/src/ui/control/fullscreen_control.test.ts +114 -0
  419. package/src/ui/control/fullscreen_control.ts +189 -0
  420. package/src/ui/control/geolocate_control.test.ts +619 -0
  421. package/src/ui/control/geolocate_control.ts +725 -0
  422. package/src/ui/control/logo_control.test.ts +88 -0
  423. package/src/ui/control/logo_control.ts +86 -0
  424. package/src/ui/control/navigation_control.test.ts +238 -0
  425. package/src/ui/control/navigation_control.ts +294 -0
  426. package/src/ui/control/scale_control.test.ts +52 -0
  427. package/src/ui/control/scale_control.ts +152 -0
  428. package/src/ui/control/terrain_control.test.ts +58 -0
  429. package/src/ui/control/terrain_control.ts +74 -0
  430. package/src/ui/default_locale.ts +25 -0
  431. package/src/ui/events.ts +758 -0
  432. package/src/ui/handler/box_zoom.test.ts +163 -0
  433. package/src/ui/handler/box_zoom.ts +171 -0
  434. package/src/ui/handler/click_zoom.ts +55 -0
  435. package/src/ui/handler/cooperative_gestures.test.ts +338 -0
  436. package/src/ui/handler/cooperative_gestures.ts +111 -0
  437. package/src/ui/handler/dblclick_zoom.test.ts +151 -0
  438. package/src/ui/handler/drag_handler.ts +174 -0
  439. package/src/ui/handler/drag_move_state_manager.ts +115 -0
  440. package/src/ui/handler/drag_pan.test.ts +487 -0
  441. package/src/ui/handler/drag_rotate.test.ts +859 -0
  442. package/src/ui/handler/handler_util.ts +10 -0
  443. package/src/ui/handler/keyboard.test.ts +235 -0
  444. package/src/ui/handler/keyboard.ts +212 -0
  445. package/src/ui/handler/map_event.test.ts +158 -0
  446. package/src/ui/handler/map_event.ts +161 -0
  447. package/src/ui/handler/mouse.ts +92 -0
  448. package/src/ui/handler/mouse_handler_interface.test.ts +111 -0
  449. package/src/ui/handler/mouse_rotate.test.ts +62 -0
  450. package/src/ui/handler/one_finger_touch_drag.ts +45 -0
  451. package/src/ui/handler/one_finger_touch_drag_handler_interface.test.ts +77 -0
  452. package/src/ui/handler/scroll_zoom.test.ts +382 -0
  453. package/src/ui/handler/scroll_zoom.ts +379 -0
  454. package/src/ui/handler/shim/dblclick_zoom.ts +64 -0
  455. package/src/ui/handler/shim/drag_pan.ts +104 -0
  456. package/src/ui/handler/shim/drag_rotate.ts +76 -0
  457. package/src/ui/handler/shim/two_fingers_touch.ts +112 -0
  458. package/src/ui/handler/tap_drag_zoom.test.ts +113 -0
  459. package/src/ui/handler/tap_drag_zoom.ts +112 -0
  460. package/src/ui/handler/tap_recognizer.ts +138 -0
  461. package/src/ui/handler/tap_zoom.ts +98 -0
  462. package/src/ui/handler/touch_pan.ts +115 -0
  463. package/src/ui/handler/transform-provider.ts +44 -0
  464. package/src/ui/handler/two_fingers_touch.test.ts +283 -0
  465. package/src/ui/handler/two_fingers_touch.ts +336 -0
  466. package/src/ui/handler_inertia.ts +157 -0
  467. package/src/ui/handler_manager.ts +637 -0
  468. package/src/ui/hash.test.ts +404 -0
  469. package/src/ui/hash.ts +153 -0
  470. package/src/ui/map.ts +3393 -0
  471. package/src/ui/map_tests/map_animation.test.ts +61 -0
  472. package/src/ui/map_tests/map_basic.test.ts +223 -0
  473. package/src/ui/map_tests/map_bounds.test.ts +123 -0
  474. package/src/ui/map_tests/map_calculate_camera_options.test.ts +113 -0
  475. package/src/ui/map_tests/map_canvas.test.ts +59 -0
  476. package/src/ui/map_tests/map_control.test.ts +61 -0
  477. package/src/ui/map_tests/map_disable_handlers.test.ts +38 -0
  478. package/src/ui/map_tests/map_events.test.ts +1001 -0
  479. package/src/ui/map_tests/map_feature_state.test.ts +421 -0
  480. package/src/ui/map_tests/map_images.test.ts +175 -0
  481. package/src/ui/map_tests/map_is_moving.test.ts +164 -0
  482. package/src/ui/map_tests/map_is_rotating.test.ts +62 -0
  483. package/src/ui/map_tests/map_is_zooming.test.ts +86 -0
  484. package/src/ui/map_tests/map_layer.test.ts +457 -0
  485. package/src/ui/map_tests/map_options.test.ts +64 -0
  486. package/src/ui/map_tests/map_pitch.test.ts +90 -0
  487. package/src/ui/map_tests/map_pixel_ratio.test.ts +75 -0
  488. package/src/ui/map_tests/map_query_rendered_features.test.ts +93 -0
  489. package/src/ui/map_tests/map_render.test.ts +90 -0
  490. package/src/ui/map_tests/map_request_render_frame.test.ts +51 -0
  491. package/src/ui/map_tests/map_resize.test.ts +120 -0
  492. package/src/ui/map_tests/map_style.test.ts +541 -0
  493. package/src/ui/map_tests/map_terrian.test.ts +104 -0
  494. package/src/ui/map_tests/map_webgl.test.ts +72 -0
  495. package/src/ui/map_tests/map_world_copies.test.ts +103 -0
  496. package/src/ui/map_tests/map_zoom.test.ts +95 -0
  497. package/src/ui/marker.test.ts +1149 -0
  498. package/src/ui/marker.ts +880 -0
  499. package/src/ui/popup.test.ts +827 -0
  500. package/src/ui/popup.ts +717 -0
  501. package/src/util/abort_error.ts +21 -0
  502. package/src/util/actor.test.ts +218 -0
  503. package/src/util/actor.ts +241 -0
  504. package/src/util/actor_messages.ts +149 -0
  505. package/src/util/ajax.test.ts +237 -0
  506. package/src/util/ajax.ts +297 -0
  507. package/src/util/browser.test.ts +23 -0
  508. package/src/util/browser.ts +63 -0
  509. package/src/util/color_ramp.test.ts +105 -0
  510. package/src/util/color_ramp.ts +56 -0
  511. package/src/util/config.ts +29 -0
  512. package/src/util/dictionary_coder.ts +23 -0
  513. package/src/util/dispatcher.test.ts +76 -0
  514. package/src/util/dispatcher.ts +78 -0
  515. package/src/util/dom.ts +135 -0
  516. package/src/util/evented.test.ts +231 -0
  517. package/src/util/evented.ts +178 -0
  518. package/src/util/find_pole_of_inaccessibility.test.ts +21 -0
  519. package/src/util/find_pole_of_inaccessibility.ts +130 -0
  520. package/src/util/geolocation_support.test.ts +43 -0
  521. package/src/util/geolocation_support.ts +23 -0
  522. package/src/util/global_worker_pool.ts +65 -0
  523. package/src/util/image.ts +150 -0
  524. package/src/util/image_request.test.ts +408 -0
  525. package/src/util/image_request.ts +246 -0
  526. package/src/util/intersection_tests.ts +206 -0
  527. package/src/util/is_char_in_unicode_block.test.ts +15 -0
  528. package/src/util/is_char_in_unicode_block.ts +345 -0
  529. package/src/util/offscreen_canvas_distorted.test.ts +13 -0
  530. package/src/util/offscreen_canvas_distorted.ts +39 -0
  531. package/src/util/offscreen_canvas_supported.ts +11 -0
  532. package/src/util/performance.ts +117 -0
  533. package/src/util/primitives.test.ts +140 -0
  534. package/src/util/primitives.ts +143 -0
  535. package/src/util/request_manager.ts +42 -0
  536. package/src/util/resolve_tokens.test.ts +45 -0
  537. package/src/util/resolve_tokens.ts +17 -0
  538. package/src/util/script_detection.test.ts +138 -0
  539. package/src/util/script_detection.ts +376 -0
  540. package/src/util/smart_wrap.test.ts +97 -0
  541. package/src/util/smart_wrap.ts +58 -0
  542. package/src/util/struct_array.test.ts +101 -0
  543. package/src/util/struct_array.ts +246 -0
  544. package/src/util/style.test.ts +34 -0
  545. package/src/util/style.ts +28 -0
  546. package/src/util/task_queue.test.ts +114 -0
  547. package/src/util/task_queue.ts +64 -0
  548. package/src/util/test/util.ts +185 -0
  549. package/src/util/throttle.test.ts +42 -0
  550. package/src/util/throttle.ts +28 -0
  551. package/src/util/throttled_invoker.ts +41 -0
  552. package/src/util/transferable_grid_index.test.ts +56 -0
  553. package/src/util/transferable_grid_index.ts +214 -0
  554. package/src/util/util.test.ts +414 -0
  555. package/src/util/util.ts +724 -0
  556. package/src/util/vectortile_to_geojson.ts +72 -0
  557. package/src/util/verticalize_punctuation.ts +110 -0
  558. package/src/util/web_worker.ts +16 -0
  559. package/src/util/web_worker_transfer.test.ts +153 -0
  560. package/src/util/web_worker_transfer.ts +254 -0
  561. package/src/util/webp_supported.ts +63 -0
  562. package/src/util/worker_pool.test.ts +43 -0
  563. package/src/util/worker_pool.ts +58 -0
  564. package/src/util/world_bounds.test.ts +59 -0
  565. package/src/util/world_bounds.ts +46 -0
@@ -0,0 +1,911 @@
1
+ import {
2
+ charHasUprightVerticalOrientation,
3
+ charAllowsIdeographicBreaking,
4
+ charInComplexShapingScript
5
+ } from '../util/script_detection';
6
+ import {verticalizePunctuation} from '../util/verticalize_punctuation';
7
+ import {rtlWorkerPlugin} from '../source/rtl_text_plugin_worker';
8
+ import ONE_EM from './one_em';
9
+ import {warnOnce} from '../util/util';
10
+
11
+ import type {StyleGlyph, GlyphMetrics} from '../style/style_glyph';
12
+ import {GLYPH_PBF_BORDER} from '../style/parse_glyph_pbf';
13
+ import {TextFit} from '../style/style_image';
14
+ import type {ImagePosition} from '../render/image_atlas';
15
+ import {IMAGE_PADDING} from '../render/image_atlas';
16
+ import type {Rect, GlyphPosition} from '../render/glyph_atlas';
17
+ import {Formatted, FormattedSection} from '@maplibre/maplibre-gl-style-spec';
18
+
19
+ enum WritingMode {
20
+ none = 0,
21
+ horizontal = 1,
22
+ vertical = 2,
23
+ horizontalOnly = 3
24
+ }
25
+
26
+ const SHAPING_DEFAULT_OFFSET = -17;
27
+ export {shapeText, shapeIcon, applyTextFit, fitIconToText, getAnchorAlignment, WritingMode, SHAPING_DEFAULT_OFFSET};
28
+
29
+ // The position of a glyph relative to the text's anchor point.
30
+ export type PositionedGlyph = {
31
+ glyph: number;
32
+ imageName: string | null;
33
+ x: number;
34
+ y: number;
35
+ vertical: boolean;
36
+ scale: number;
37
+ fontStack: string;
38
+ sectionIndex: number;
39
+ metrics: GlyphMetrics;
40
+ rect: Rect | null;
41
+ };
42
+
43
+ export type PositionedLine = {
44
+ positionedGlyphs: Array<PositionedGlyph>;
45
+ lineOffset: number;
46
+ };
47
+
48
+ // A collection of positioned glyphs and some metadata
49
+ export type Shaping = {
50
+ positionedLines: Array<PositionedLine>;
51
+ top: number;
52
+ bottom: number;
53
+ left: number;
54
+ right: number;
55
+ writingMode: WritingMode.horizontal | WritingMode.vertical;
56
+ text: string;
57
+ iconsInText: boolean;
58
+ verticalizable: boolean;
59
+ };
60
+
61
+ function isEmpty(positionedLines: Array<PositionedLine>) {
62
+ for (const line of positionedLines) {
63
+ if (line.positionedGlyphs.length !== 0) {
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+
70
+ export type SymbolAnchor = 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
71
+ export type TextJustify = 'left' | 'center' | 'right';
72
+
73
+ // Max number of images in label is 6401 U+E000–U+F8FF that covers
74
+ // Basic Multilingual Plane Unicode Private Use Area (PUA).
75
+ const PUAbegin = 0xE000;
76
+ const PUAend = 0xF8FF;
77
+
78
+ class SectionOptions {
79
+ // Text options
80
+ scale: number;
81
+ fontStack: string;
82
+ // Image options
83
+ imageName: string | null;
84
+
85
+ constructor() {
86
+ this.scale = 1.0;
87
+ this.fontStack = '';
88
+ this.imageName = null;
89
+ }
90
+
91
+ static forText(scale: number | null, fontStack: string) {
92
+ const textOptions = new SectionOptions();
93
+ textOptions.scale = scale || 1;
94
+ textOptions.fontStack = fontStack;
95
+ return textOptions;
96
+ }
97
+
98
+ static forImage(imageName: string) {
99
+ const imageOptions = new SectionOptions();
100
+ imageOptions.imageName = imageName;
101
+ return imageOptions;
102
+ }
103
+
104
+ }
105
+
106
+ class TaggedString {
107
+ text: string;
108
+ sectionIndex: Array<number>; // maps each character in 'text' to its corresponding entry in 'sections'
109
+ sections: Array<SectionOptions>;
110
+ imageSectionID: number | null;
111
+
112
+ constructor() {
113
+ this.text = '';
114
+ this.sectionIndex = [];
115
+ this.sections = [];
116
+ this.imageSectionID = null;
117
+ }
118
+
119
+ static fromFeature(text: Formatted, defaultFontStack: string) {
120
+ const result = new TaggedString();
121
+ for (let i = 0; i < text.sections.length; i++) {
122
+ const section = text.sections[i];
123
+ if (!section.image) {
124
+ result.addTextSection(section, defaultFontStack);
125
+ } else {
126
+ result.addImageSection(section);
127
+ }
128
+ }
129
+ return result;
130
+ }
131
+
132
+ length(): number {
133
+ return this.text.length;
134
+ }
135
+
136
+ getSection(index: number): SectionOptions {
137
+ return this.sections[this.sectionIndex[index]];
138
+ }
139
+
140
+ getSectionIndex(index: number): number {
141
+ return this.sectionIndex[index];
142
+ }
143
+
144
+ getCharCode(index: number): number {
145
+ return this.text.charCodeAt(index);
146
+ }
147
+
148
+ verticalizePunctuation() {
149
+ this.text = verticalizePunctuation(this.text);
150
+ }
151
+
152
+ trim() {
153
+ let beginningWhitespace = 0;
154
+ for (let i = 0;
155
+ i < this.text.length && whitespace[this.text.charCodeAt(i)];
156
+ i++) {
157
+ beginningWhitespace++;
158
+ }
159
+ let trailingWhitespace = this.text.length;
160
+ for (let i = this.text.length - 1;
161
+ i >= 0 && i >= beginningWhitespace && whitespace[this.text.charCodeAt(i)];
162
+ i--) {
163
+ trailingWhitespace--;
164
+ }
165
+ this.text = this.text.substring(beginningWhitespace, trailingWhitespace);
166
+ this.sectionIndex = this.sectionIndex.slice(beginningWhitespace, trailingWhitespace);
167
+ }
168
+
169
+ substring(start: number, end: number): TaggedString {
170
+ const substring = new TaggedString();
171
+ substring.text = this.text.substring(start, end);
172
+ substring.sectionIndex = this.sectionIndex.slice(start, end);
173
+ substring.sections = this.sections;
174
+ return substring;
175
+ }
176
+
177
+ toString(): string {
178
+ return this.text;
179
+ }
180
+
181
+ getMaxScale() {
182
+ return this.sectionIndex.reduce((max, index) => Math.max(max, this.sections[index].scale), 0);
183
+ }
184
+
185
+ addTextSection(section: FormattedSection, defaultFontStack: string) {
186
+ this.text += section.text;
187
+ this.sections.push(SectionOptions.forText(section.scale, section.fontStack || defaultFontStack));
188
+ const index = this.sections.length - 1;
189
+ for (let i = 0; i < section.text.length; ++i) {
190
+ this.sectionIndex.push(index);
191
+ }
192
+ }
193
+
194
+ addImageSection(section: FormattedSection) {
195
+ const imageName = section.image ? section.image.name : '';
196
+ if (imageName.length === 0) {
197
+ warnOnce('Can\'t add FormattedSection with an empty image.');
198
+ return;
199
+ }
200
+
201
+ const nextImageSectionCharCode = this.getNextImageSectionCharCode();
202
+ if (!nextImageSectionCharCode) {
203
+ warnOnce(`Reached maximum number of images ${PUAend - PUAbegin + 2}`);
204
+ return;
205
+ }
206
+
207
+ this.text += String.fromCharCode(nextImageSectionCharCode);
208
+ this.sections.push(SectionOptions.forImage(imageName));
209
+ this.sectionIndex.push(this.sections.length - 1);
210
+ }
211
+
212
+ getNextImageSectionCharCode(): number | null {
213
+ if (!this.imageSectionID) {
214
+ this.imageSectionID = PUAbegin;
215
+ return this.imageSectionID;
216
+ }
217
+
218
+ if (this.imageSectionID >= PUAend) return null;
219
+ return ++this.imageSectionID;
220
+ }
221
+ }
222
+
223
+ function breakLines(input: TaggedString, lineBreakPoints: Array<number>): Array<TaggedString> {
224
+ const lines = [];
225
+ const text = input.text;
226
+ let start = 0;
227
+ for (const lineBreak of lineBreakPoints) {
228
+ lines.push(input.substring(start, lineBreak));
229
+ start = lineBreak;
230
+ }
231
+
232
+ if (start < text.length) {
233
+ lines.push(input.substring(start, text.length));
234
+ }
235
+ return lines;
236
+ }
237
+
238
+ function shapeText(
239
+ text: Formatted,
240
+ glyphMap: {
241
+ [_: string]: {
242
+ [_: number]: StyleGlyph;
243
+ };
244
+ },
245
+ glyphPositions: {
246
+ [_: string]: {
247
+ [_: number]: GlyphPosition;
248
+ };
249
+ },
250
+ imagePositions: {[_: string]: ImagePosition},
251
+ defaultFontStack: string,
252
+ maxWidth: number,
253
+ lineHeight: number,
254
+ textAnchor: SymbolAnchor,
255
+ textJustify: TextJustify,
256
+ spacing: number,
257
+ translate: [number, number],
258
+ writingMode: WritingMode.horizontal | WritingMode.vertical,
259
+ allowVerticalPlacement: boolean,
260
+ layoutTextSize: number,
261
+ layoutTextSizeThisZoom: number
262
+ ): Shaping | false {
263
+ const logicalInput = TaggedString.fromFeature(text, defaultFontStack);
264
+
265
+ if (writingMode === WritingMode.vertical) {
266
+ logicalInput.verticalizePunctuation();
267
+ }
268
+
269
+ let lines: Array<TaggedString>;
270
+
271
+ const {processBidirectionalText, processStyledBidirectionalText} = rtlWorkerPlugin;
272
+ if (processBidirectionalText && logicalInput.sections.length === 1) {
273
+ // Bidi doesn't have to be style-aware
274
+ lines = [];
275
+ const untaggedLines =
276
+ processBidirectionalText(logicalInput.toString(),
277
+ determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize));
278
+ for (const line of untaggedLines) {
279
+ const taggedLine = new TaggedString();
280
+ taggedLine.text = line;
281
+ taggedLine.sections = logicalInput.sections;
282
+ for (let i = 0; i < line.length; i++) {
283
+ taggedLine.sectionIndex.push(0);
284
+ }
285
+ lines.push(taggedLine);
286
+ }
287
+ } else if (processStyledBidirectionalText) {
288
+ // Need version of mapbox-gl-rtl-text with style support for combining RTL text
289
+ // with formatting
290
+ lines = [];
291
+ const processedLines =
292
+ processStyledBidirectionalText(logicalInput.text,
293
+ logicalInput.sectionIndex,
294
+ determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize));
295
+ for (const line of processedLines) {
296
+ const taggedLine = new TaggedString();
297
+ taggedLine.text = line[0];
298
+ taggedLine.sectionIndex = line[1];
299
+ taggedLine.sections = logicalInput.sections;
300
+ lines.push(taggedLine);
301
+ }
302
+ } else {
303
+ lines = breakLines(logicalInput, determineLineBreaks(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize));
304
+ }
305
+
306
+ const positionedLines = [];
307
+ const shaping = {
308
+ positionedLines,
309
+ text: logicalInput.toString(),
310
+ top: translate[1],
311
+ bottom: translate[1],
312
+ left: translate[0],
313
+ right: translate[0],
314
+ writingMode,
315
+ iconsInText: false,
316
+ verticalizable: false
317
+ };
318
+
319
+ shapeLines(shaping, glyphMap, glyphPositions, imagePositions, lines, lineHeight, textAnchor, textJustify, writingMode, spacing, allowVerticalPlacement, layoutTextSizeThisZoom);
320
+ if (isEmpty(positionedLines)) return false;
321
+
322
+ return shaping;
323
+ }
324
+
325
+ // using computed properties due to https://github.com/facebook/flow/issues/380
326
+ /* eslint no-useless-computed-key: 0 */
327
+
328
+ const whitespace: {
329
+ [_: number]: boolean;
330
+ } = {
331
+ [0x09]: true, // tab
332
+ [0x0a]: true, // newline
333
+ [0x0b]: true, // vertical tab
334
+ [0x0c]: true, // form feed
335
+ [0x0d]: true, // carriage return
336
+ [0x20]: true, // space
337
+ };
338
+
339
+ const breakable: {
340
+ [_: number]: boolean;
341
+ } = {
342
+ [0x0a]: true, // newline
343
+ [0x20]: true, // space
344
+ [0x26]: true, // ampersand
345
+ [0x29]: true, // right parenthesis
346
+ [0x2b]: true, // plus sign
347
+ [0x2d]: true, // hyphen-minus
348
+ [0x2f]: true, // solidus
349
+ [0xad]: true, // soft hyphen
350
+ [0xb7]: true, // middle dot
351
+ [0x200b]: true, // zero-width space
352
+ [0x2010]: true, // hyphen
353
+ [0x2013]: true, // en dash
354
+ [0x2027]: true // interpunct
355
+ // Many other characters may be reasonable breakpoints
356
+ // Consider "neutral orientation" characters at scriptDetection.charHasNeutralVerticalOrientation
357
+ // See https://github.com/mapbox/mapbox-gl-js/issues/3658
358
+ };
359
+
360
+ // Allow breaks depending on the following character
361
+ const breakableBefore: {
362
+ [_: number]: boolean;
363
+ } = {
364
+ [0x28]: true, // left parenthesis
365
+ };
366
+
367
+ function getGlyphAdvance(
368
+ codePoint: number,
369
+ section: SectionOptions,
370
+ glyphMap: {
371
+ [_: string]: {
372
+ [_: number]: StyleGlyph;
373
+ };
374
+ },
375
+ imagePositions: {[_: string]: ImagePosition},
376
+ spacing: number,
377
+ layoutTextSize: number
378
+ ): number {
379
+ if (!section.imageName) {
380
+ const positions = glyphMap[section.fontStack];
381
+ const glyph = positions && positions[codePoint];
382
+ if (!glyph) return 0;
383
+ return glyph.metrics.advance * section.scale + spacing;
384
+ } else {
385
+ const imagePosition = imagePositions[section.imageName];
386
+ if (!imagePosition) return 0;
387
+ return imagePosition.displaySize[0] * section.scale * ONE_EM / layoutTextSize + spacing;
388
+ }
389
+ }
390
+
391
+ function determineAverageLineWidth(logicalInput: TaggedString,
392
+ spacing: number,
393
+ maxWidth: number,
394
+ glyphMap: {
395
+ [_: string]: {
396
+ [_: number]: StyleGlyph;
397
+ };
398
+ },
399
+ imagePositions: {[_: string]: ImagePosition},
400
+ layoutTextSize: number) {
401
+ let totalWidth = 0;
402
+
403
+ for (let index = 0; index < logicalInput.length(); index++) {
404
+ const section = logicalInput.getSection(index);
405
+ totalWidth += getGlyphAdvance(logicalInput.getCharCode(index), section, glyphMap, imagePositions, spacing, layoutTextSize);
406
+ }
407
+
408
+ const lineCount = Math.max(1, Math.ceil(totalWidth / maxWidth));
409
+ return totalWidth / lineCount;
410
+ }
411
+
412
+ function calculateBadness(lineWidth: number,
413
+ targetWidth: number,
414
+ penalty: number,
415
+ isLastBreak: boolean) {
416
+ const raggedness = Math.pow(lineWidth - targetWidth, 2);
417
+ if (isLastBreak) {
418
+ // Favor finals lines shorter than average over longer than average
419
+ if (lineWidth < targetWidth) {
420
+ return raggedness / 2;
421
+ } else {
422
+ return raggedness * 2;
423
+ }
424
+ }
425
+
426
+ return raggedness + Math.abs(penalty) * penalty;
427
+ }
428
+
429
+ function calculatePenalty(codePoint: number, nextCodePoint: number, penalizableIdeographicBreak: boolean) {
430
+ let penalty = 0;
431
+ // Force break on newline
432
+ if (codePoint === 0x0a) {
433
+ penalty -= 10000;
434
+ }
435
+ // Penalize breaks between characters that allow ideographic breaking because
436
+ // they are less preferable than breaks at spaces (or zero width spaces).
437
+ if (penalizableIdeographicBreak) {
438
+ penalty += 150;
439
+ }
440
+
441
+ // Penalize open parenthesis at end of line
442
+ if (codePoint === 0x28 || codePoint === 0xff08) {
443
+ penalty += 50;
444
+ }
445
+
446
+ // Penalize close parenthesis at beginning of line
447
+ if (nextCodePoint === 0x29 || nextCodePoint === 0xff09) {
448
+ penalty += 50;
449
+ }
450
+ return penalty;
451
+ }
452
+
453
+ type Break = {
454
+ index: number;
455
+ x: number;
456
+ priorBreak: Break;
457
+ badness: number;
458
+ };
459
+
460
+ function evaluateBreak(
461
+ breakIndex: number,
462
+ breakX: number,
463
+ targetWidth: number,
464
+ potentialBreaks: Array<Break>,
465
+ penalty: number,
466
+ isLastBreak: boolean
467
+ ): Break {
468
+ // We could skip evaluating breaks where the line length (breakX - priorBreak.x) > maxWidth
469
+ // ...but in fact we allow lines longer than maxWidth (if there's no break points)
470
+ // ...and when targetWidth and maxWidth are close, strictly enforcing maxWidth can give
471
+ // more lopsided results.
472
+
473
+ let bestPriorBreak: Break = null;
474
+ let bestBreakBadness = calculateBadness(breakX, targetWidth, penalty, isLastBreak);
475
+
476
+ for (const potentialBreak of potentialBreaks) {
477
+ const lineWidth = breakX - potentialBreak.x;
478
+ const breakBadness =
479
+ calculateBadness(lineWidth, targetWidth, penalty, isLastBreak) + potentialBreak.badness;
480
+ if (breakBadness <= bestBreakBadness) {
481
+ bestPriorBreak = potentialBreak;
482
+ bestBreakBadness = breakBadness;
483
+ }
484
+ }
485
+
486
+ return {
487
+ index: breakIndex,
488
+ x: breakX,
489
+ priorBreak: bestPriorBreak,
490
+ badness: bestBreakBadness
491
+ };
492
+ }
493
+
494
+ function leastBadBreaks(lastLineBreak?: Break | null): Array<number> {
495
+ if (!lastLineBreak) {
496
+ return [];
497
+ }
498
+ return leastBadBreaks(lastLineBreak.priorBreak).concat(lastLineBreak.index);
499
+ }
500
+
501
+ function determineLineBreaks(
502
+ logicalInput: TaggedString,
503
+ spacing: number,
504
+ maxWidth: number,
505
+ glyphMap: {
506
+ [_: string]: {
507
+ [_: number]: StyleGlyph;
508
+ };
509
+ },
510
+ imagePositions: {[_: string]: ImagePosition},
511
+ layoutTextSize: number
512
+ ): Array<number> {
513
+ if (!logicalInput)
514
+ return [];
515
+
516
+ const potentialLineBreaks = [];
517
+ const targetWidth = determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize);
518
+
519
+ const hasServerSuggestedBreakpoints = logicalInput.text.indexOf('\u200b') >= 0;
520
+
521
+ let currentX = 0;
522
+
523
+ for (let i = 0; i < logicalInput.length(); i++) {
524
+ const section = logicalInput.getSection(i);
525
+ const codePoint = logicalInput.getCharCode(i);
526
+ if (!whitespace[codePoint]) currentX += getGlyphAdvance(codePoint, section, glyphMap, imagePositions, spacing, layoutTextSize);
527
+
528
+ // Ideographic characters, spaces, and word-breaking punctuation that often appear without
529
+ // surrounding spaces.
530
+ if ((i < logicalInput.length() - 1)) {
531
+ const ideographicBreak = charAllowsIdeographicBreaking(codePoint);
532
+ if (breakable[codePoint] || ideographicBreak || section.imageName || (i !== logicalInput.length() - 2 && breakableBefore[logicalInput.getCharCode(i + 1)])) {
533
+
534
+ potentialLineBreaks.push(
535
+ evaluateBreak(
536
+ i + 1,
537
+ currentX,
538
+ targetWidth,
539
+ potentialLineBreaks,
540
+ calculatePenalty(codePoint, logicalInput.getCharCode(i + 1), ideographicBreak && hasServerSuggestedBreakpoints),
541
+ false));
542
+ }
543
+ }
544
+ }
545
+
546
+ return leastBadBreaks(
547
+ evaluateBreak(
548
+ logicalInput.length(),
549
+ currentX,
550
+ targetWidth,
551
+ potentialLineBreaks,
552
+ 0,
553
+ true));
554
+ }
555
+
556
+ function getAnchorAlignment(anchor: SymbolAnchor) {
557
+ let horizontalAlign = 0.5, verticalAlign = 0.5;
558
+
559
+ switch (anchor) {
560
+ case 'right':
561
+ case 'top-right':
562
+ case 'bottom-right':
563
+ horizontalAlign = 1;
564
+ break;
565
+ case 'left':
566
+ case 'top-left':
567
+ case 'bottom-left':
568
+ horizontalAlign = 0;
569
+ break;
570
+ }
571
+
572
+ switch (anchor) {
573
+ case 'bottom':
574
+ case 'bottom-right':
575
+ case 'bottom-left':
576
+ verticalAlign = 1;
577
+ break;
578
+ case 'top':
579
+ case 'top-right':
580
+ case 'top-left':
581
+ verticalAlign = 0;
582
+ break;
583
+ }
584
+
585
+ return {horizontalAlign, verticalAlign};
586
+ }
587
+
588
+ function shapeLines(shaping: Shaping,
589
+ glyphMap: {
590
+ [_: string]: {
591
+ [_: number]: StyleGlyph;
592
+ };
593
+ },
594
+ glyphPositions: {
595
+ [_: string]: {
596
+ [_: number]: GlyphPosition;
597
+ };
598
+ },
599
+ imagePositions: {[_: string]: ImagePosition},
600
+ lines: Array<TaggedString>,
601
+ lineHeight: number,
602
+ textAnchor: SymbolAnchor,
603
+ textJustify: TextJustify,
604
+ writingMode: WritingMode.horizontal | WritingMode.vertical,
605
+ spacing: number,
606
+ allowVerticalPlacement: boolean,
607
+ layoutTextSizeThisZoom: number) {
608
+
609
+ let x = 0;
610
+ let y = SHAPING_DEFAULT_OFFSET;
611
+
612
+ let maxLineLength = 0;
613
+ let maxLineHeight = 0;
614
+
615
+ const justify =
616
+ textJustify === 'right' ? 1 :
617
+ textJustify === 'left' ? 0 : 0.5;
618
+
619
+ let lineIndex = 0;
620
+ for (const line of lines) {
621
+ line.trim();
622
+
623
+ const lineMaxScale = line.getMaxScale();
624
+ const maxLineOffset = (lineMaxScale - 1) * ONE_EM;
625
+ const positionedLine = {positionedGlyphs: [], lineOffset: 0};
626
+ shaping.positionedLines[lineIndex] = positionedLine;
627
+ const positionedGlyphs = positionedLine.positionedGlyphs;
628
+ let lineOffset = 0.0;
629
+
630
+ if (!line.length()) {
631
+ y += lineHeight; // Still need a line feed after empty line
632
+ ++lineIndex;
633
+ continue;
634
+ }
635
+
636
+ for (let i = 0; i < line.length(); i++) {
637
+ const section = line.getSection(i);
638
+ const sectionIndex = line.getSectionIndex(i);
639
+ const codePoint = line.getCharCode(i);
640
+ let baselineOffset = 0.0;
641
+ let metrics = null;
642
+ let rect = null;
643
+ let imageName = null;
644
+ let verticalAdvance = ONE_EM;
645
+ const vertical = !(writingMode === WritingMode.horizontal ||
646
+ // Don't verticalize glyphs that have no upright orientation if vertical placement is disabled.
647
+ (!allowVerticalPlacement && !charHasUprightVerticalOrientation(codePoint)) ||
648
+ // If vertical placement is enabled, don't verticalize glyphs that
649
+ // are from complex text layout script, or whitespaces.
650
+ (allowVerticalPlacement && (whitespace[codePoint] || charInComplexShapingScript(codePoint))));
651
+
652
+ if (!section.imageName) {
653
+ const positions = glyphPositions[section.fontStack];
654
+ const glyphPosition = positions && positions[codePoint];
655
+ if (glyphPosition && glyphPosition.rect) {
656
+ rect = glyphPosition.rect;
657
+ metrics = glyphPosition.metrics;
658
+ } else {
659
+ const glyphs = glyphMap[section.fontStack];
660
+ const glyph = glyphs && glyphs[codePoint];
661
+ if (!glyph) continue;
662
+ metrics = glyph.metrics;
663
+ }
664
+
665
+ // We don't know the baseline, but since we're laying out
666
+ // at 24 points, we can calculate how much it will move when
667
+ // we scale up or down.
668
+ baselineOffset = (lineMaxScale - section.scale) * ONE_EM;
669
+ } else {
670
+ const imagePosition = imagePositions[section.imageName];
671
+ if (!imagePosition) continue;
672
+ imageName = section.imageName;
673
+ shaping.iconsInText = shaping.iconsInText || true;
674
+ rect = imagePosition.paddedRect;
675
+ const size = imagePosition.displaySize;
676
+ // If needed, allow to set scale factor for an image using
677
+ // alias "image-scale" that could be alias for "font-scale"
678
+ // when FormattedSection is an image section.
679
+ section.scale = section.scale * ONE_EM / layoutTextSizeThisZoom;
680
+
681
+ metrics = {width: size[0],
682
+ height: size[1],
683
+ left: IMAGE_PADDING,
684
+ top: -GLYPH_PBF_BORDER,
685
+ advance: vertical ? size[1] : size[0]};
686
+
687
+ // Difference between one EM and an image size.
688
+ // Aligns bottom of an image to a baseline level.
689
+ const imageOffset = ONE_EM - size[1] * section.scale;
690
+ baselineOffset = maxLineOffset + imageOffset;
691
+ verticalAdvance = metrics.advance;
692
+
693
+ // Difference between height of an image and one EM at max line scale.
694
+ // Pushes current line down if an image size is over 1 EM at max line scale.
695
+ const offset = vertical ? size[0] * section.scale - ONE_EM * lineMaxScale :
696
+ size[1] * section.scale - ONE_EM * lineMaxScale;
697
+ if (offset > 0 && offset > lineOffset) {
698
+ lineOffset = offset;
699
+ }
700
+ }
701
+
702
+ if (!vertical) {
703
+ positionedGlyphs.push({glyph: codePoint, imageName, x, y: y + baselineOffset, vertical, scale: section.scale, fontStack: section.fontStack, sectionIndex, metrics, rect});
704
+ x += metrics.advance * section.scale + spacing;
705
+ } else {
706
+ shaping.verticalizable = true;
707
+ positionedGlyphs.push({glyph: codePoint, imageName, x, y: y + baselineOffset, vertical, scale: section.scale, fontStack: section.fontStack, sectionIndex, metrics, rect});
708
+ x += verticalAdvance * section.scale + spacing;
709
+ }
710
+ }
711
+
712
+ // Only justify if we placed at least one glyph
713
+ if (positionedGlyphs.length !== 0) {
714
+ const lineLength = x - spacing;
715
+ maxLineLength = Math.max(lineLength, maxLineLength);
716
+ justifyLine(positionedGlyphs, 0, positionedGlyphs.length - 1, justify, lineOffset);
717
+ }
718
+
719
+ x = 0;
720
+ const currentLineHeight = lineHeight * lineMaxScale + lineOffset;
721
+ positionedLine.lineOffset = Math.max(lineOffset, maxLineOffset);
722
+ y += currentLineHeight;
723
+ maxLineHeight = Math.max(currentLineHeight, maxLineHeight);
724
+ ++lineIndex;
725
+ }
726
+
727
+ // Calculate the bounding box and justify / align text block.
728
+ const height = y - SHAPING_DEFAULT_OFFSET;
729
+ const {horizontalAlign, verticalAlign} = getAnchorAlignment(textAnchor);
730
+ align(shaping.positionedLines, justify, horizontalAlign, verticalAlign, maxLineLength, maxLineHeight, lineHeight, height, lines.length);
731
+
732
+ shaping.top += -verticalAlign * height;
733
+ shaping.bottom = shaping.top + height;
734
+ shaping.left += -horizontalAlign * maxLineLength;
735
+ shaping.right = shaping.left + maxLineLength;
736
+ }
737
+
738
+ // justify right = 1, left = 0, center = 0.5
739
+ function justifyLine(positionedGlyphs: Array<PositionedGlyph>,
740
+ start: number,
741
+ end: number,
742
+ justify: 1 | 0 | 0.5,
743
+ lineOffset: number) {
744
+ if (!justify && !lineOffset)
745
+ return;
746
+
747
+ const lastPositionedGlyph = positionedGlyphs[end];
748
+ const lastAdvance = lastPositionedGlyph.metrics.advance * lastPositionedGlyph.scale;
749
+ const lineIndent = (positionedGlyphs[end].x + lastAdvance) * justify;
750
+
751
+ for (let j = start; j <= end; j++) {
752
+ positionedGlyphs[j].x -= lineIndent;
753
+ positionedGlyphs[j].y += lineOffset;
754
+ }
755
+ }
756
+
757
+ function align(positionedLines: Array<PositionedLine>,
758
+ justify: number,
759
+ horizontalAlign: number,
760
+ verticalAlign: number,
761
+ maxLineLength: number,
762
+ maxLineHeight: number,
763
+ lineHeight: number,
764
+ blockHeight: number,
765
+ lineCount: number) {
766
+ const shiftX = (justify - horizontalAlign) * maxLineLength;
767
+ let shiftY = 0;
768
+
769
+ if (maxLineHeight !== lineHeight) {
770
+ shiftY = -blockHeight * verticalAlign - SHAPING_DEFAULT_OFFSET;
771
+ } else {
772
+ shiftY = (-verticalAlign * lineCount + 0.5) * lineHeight;
773
+ }
774
+
775
+ for (const line of positionedLines) {
776
+ for (const positionedGlyph of line.positionedGlyphs) {
777
+ positionedGlyph.x += shiftX;
778
+ positionedGlyph.y += shiftY;
779
+ }
780
+ }
781
+ }
782
+
783
+ export type PositionedIcon = {
784
+ image: ImagePosition;
785
+ top: number;
786
+ bottom: number;
787
+ left: number;
788
+ right: number;
789
+ collisionPadding?: [number, number, number, number];
790
+ };
791
+
792
+ function shapeIcon(
793
+ image: ImagePosition,
794
+ iconOffset: [number, number],
795
+ iconAnchor: SymbolAnchor
796
+ ): PositionedIcon {
797
+ const {horizontalAlign, verticalAlign} = getAnchorAlignment(iconAnchor);
798
+ const dx = iconOffset[0];
799
+ const dy = iconOffset[1];
800
+ const x1 = dx - image.displaySize[0] * horizontalAlign;
801
+ const x2 = x1 + image.displaySize[0];
802
+ const y1 = dy - image.displaySize[1] * verticalAlign;
803
+ const y2 = y1 + image.displaySize[1];
804
+ return {image, top: y1, bottom: y2, left: x1, right: x2};
805
+ }
806
+
807
+ export interface Box {
808
+ x1: number;
809
+ y1: number;
810
+ x2: number;
811
+ y2: number;
812
+ }
813
+
814
+ /**
815
+ * Called after a PositionedIcon has already been run through fitIconToText,
816
+ * but needs further adjustment to apply textFitWidth and textFitHeight.
817
+ * @param shapedIcon - The icon that will be adjusted.
818
+ * @returns Extents of the shapedIcon with text fit adjustments if necessary.
819
+ */
820
+ function applyTextFit(shapedIcon: PositionedIcon): Box {
821
+ // Assume shapedIcon.image is set or this wouldn't be called.
822
+ // Size of the icon after it was adjusted using stretchX and Y
823
+ let iconLeft = shapedIcon.left;
824
+ let iconTop = shapedIcon.top;
825
+ let iconWidth = shapedIcon.right - iconLeft;
826
+ let iconHeight = shapedIcon.bottom - iconTop;
827
+ // Size of the original content area
828
+ const contentWidth = shapedIcon.image.content[2] - shapedIcon.image.content[0];
829
+ const contentHeight = shapedIcon.image.content[3] - shapedIcon.image.content[1];
830
+ const textFitWidth = shapedIcon.image.textFitWidth ?? TextFit.stretchOrShrink;
831
+ const textFitHeight = shapedIcon.image.textFitHeight ?? TextFit.stretchOrShrink;
832
+ const contentAspectRatio = contentWidth / contentHeight;
833
+ // Scale to the proportional axis first note that height takes precedence if
834
+ // both axes are set to proportional.
835
+ if (textFitHeight === TextFit.proportional) {
836
+ if ((textFitWidth === TextFit.stretchOnly && iconWidth / iconHeight < contentAspectRatio) || textFitWidth === TextFit.proportional) {
837
+ // Push the width of the icon back out to match the content aspect ratio
838
+ const newIconWidth = Math.ceil(iconHeight * contentAspectRatio);
839
+ iconLeft *= newIconWidth / iconWidth;
840
+ iconWidth = newIconWidth;
841
+ }
842
+ } else if (textFitWidth === TextFit.proportional) {
843
+ if (textFitHeight === TextFit.stretchOnly && contentAspectRatio !== 0 && iconWidth / iconHeight > contentAspectRatio) {
844
+ // Push the height of the icon back out to match the content aspect ratio
845
+ const newIconHeight = Math.ceil(iconWidth / contentAspectRatio);
846
+ iconTop *= newIconHeight / iconHeight;
847
+ iconHeight = newIconHeight;
848
+ }
849
+ } else {
850
+ // If neither textFitHeight nor textFitWidth are proportional then
851
+ // there is no effect since the content rectangle should be precisely
852
+ // matched to the content
853
+ }
854
+ return {x1: iconLeft, y1: iconTop, x2: iconLeft + iconWidth, y2: iconTop + iconHeight};
855
+ }
856
+
857
+ function fitIconToText(
858
+ shapedIcon: PositionedIcon,
859
+ shapedText: Shaping,
860
+ textFit: string,
861
+ padding: [number, number, number, number],
862
+ iconOffset: [number, number],
863
+ fontScale: number
864
+ ): PositionedIcon {
865
+
866
+ const image = shapedIcon.image;
867
+
868
+ let collisionPadding;
869
+ if (image.content) {
870
+ const content = image.content;
871
+ const pixelRatio = image.pixelRatio || 1;
872
+ collisionPadding = [
873
+ content[0] / pixelRatio,
874
+ content[1] / pixelRatio,
875
+ image.displaySize[0] - content[2] / pixelRatio,
876
+ image.displaySize[1] - content[3] / pixelRatio
877
+ ];
878
+ }
879
+
880
+ // We don't respect the icon-anchor, because icon-text-fit is set. Instead,
881
+ // the icon will be centered on the text, then stretched in the given
882
+ // dimensions.
883
+
884
+ const textLeft = shapedText.left * fontScale;
885
+ const textRight = shapedText.right * fontScale;
886
+
887
+ let top, right, bottom, left;
888
+ if (textFit === 'width' || textFit === 'both') {
889
+ // Stretched horizontally to the text width
890
+ left = iconOffset[0] + textLeft - padding[3];
891
+ right = iconOffset[0] + textRight + padding[1];
892
+ } else {
893
+ // Centered on the text
894
+ left = iconOffset[0] + (textLeft + textRight - image.displaySize[0]) / 2;
895
+ right = left + image.displaySize[0];
896
+ }
897
+
898
+ const textTop = shapedText.top * fontScale;
899
+ const textBottom = shapedText.bottom * fontScale;
900
+ if (textFit === 'height' || textFit === 'both') {
901
+ // Stretched vertically to the text height
902
+ top = iconOffset[1] + textTop - padding[0];
903
+ bottom = iconOffset[1] + textBottom + padding[2];
904
+ } else {
905
+ // Centered on the text
906
+ top = iconOffset[1] + (textTop + textBottom - image.displaySize[1]) / 2;
907
+ bottom = top + image.displaySize[1];
908
+ }
909
+
910
+ return {image, top, right, bottom, left, collisionPadding};
911
+ }