@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.
Files changed (356) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +25 -0
  3. package/build/min/.dir +0 -0
  4. package/build/min/package.json +3 -0
  5. package/build/min/src/shaders/_prelude.fragment.glsl.txt +13 -0
  6. package/build/min/src/shaders/_prelude.vertex.glsl.txt +14 -0
  7. package/build/min/src/shaders/background.fragment.glsl.txt +5 -0
  8. package/build/min/src/shaders/background.vertex.glsl.txt +1 -0
  9. package/build/min/src/shaders/background_pattern.fragment.glsl.txt +5 -0
  10. package/build/min/src/shaders/background_pattern.vertex.glsl.txt +1 -0
  11. package/build/min/src/shaders/circle.fragment.glsl.txt +20 -0
  12. package/build/min/src/shaders/circle.vertex.glsl.txt +17 -0
  13. package/build/min/src/shaders/clipping_mask.fragment.glsl.txt +1 -0
  14. package/build/min/src/shaders/clipping_mask.vertex.glsl.txt +1 -0
  15. package/build/min/src/shaders/collision_box.fragment.glsl.txt +1 -0
  16. package/build/min/src/shaders/collision_box.vertex.glsl.txt +1 -0
  17. package/build/min/src/shaders/collision_circle.fragment.glsl.txt +1 -0
  18. package/build/min/src/shaders/collision_circle.vertex.glsl.txt +1 -0
  19. package/build/min/src/shaders/debug.fragment.glsl.txt +1 -0
  20. package/build/min/src/shaders/debug.vertex.glsl.txt +1 -0
  21. package/build/min/src/shaders/fill.fragment.glsl.txt +10 -0
  22. package/build/min/src/shaders/fill.vertex.glsl.txt +7 -0
  23. package/build/min/src/shaders/fill_extrusion.fragment.glsl.txt +13 -0
  24. package/build/min/src/shaders/fill_extrusion.vertex.glsl.txt +9 -0
  25. package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.txt +15 -0
  26. package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.txt +11 -0
  27. package/build/min/src/shaders/fill_outline.fragment.glsl.txt +10 -0
  28. package/build/min/src/shaders/fill_outline.vertex.glsl.txt +7 -0
  29. package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.txt +13 -0
  30. package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.txt +9 -0
  31. package/build/min/src/shaders/fill_pattern.fragment.glsl.txt +13 -0
  32. package/build/min/src/shaders/fill_pattern.vertex.glsl.txt +9 -0
  33. package/build/min/src/shaders/heatmap.fragment.glsl.txt +10 -0
  34. package/build/min/src/shaders/heatmap.vertex.glsl.txt +8 -0
  35. package/build/min/src/shaders/heatmap_texture.fragment.glsl.txt +5 -0
  36. package/build/min/src/shaders/heatmap_texture.vertex.glsl.txt +1 -0
  37. package/build/min/src/shaders/hillshade.fragment.glsl.txt +7 -0
  38. package/build/min/src/shaders/hillshade.vertex.glsl.txt +1 -0
  39. package/build/min/src/shaders/hillshade_prepare.fragment.glsl.txt +8 -0
  40. package/build/min/src/shaders/hillshade_prepare.vertex.glsl.txt +1 -0
  41. package/build/min/src/shaders/line.fragment.glsl.txt +12 -0
  42. package/build/min/src/shaders/line.vertex.glsl.txt +17 -0
  43. package/build/min/src/shaders/line_gradient.fragment.glsl.txt +10 -0
  44. package/build/min/src/shaders/line_gradient.vertex.glsl.txt +16 -0
  45. package/build/min/src/shaders/line_pattern.fragment.glsl.txt +15 -0
  46. package/build/min/src/shaders/line_pattern.vertex.glsl.txt +20 -0
  47. package/build/min/src/shaders/line_sdf.fragment.glsl.txt +17 -0
  48. package/build/min/src/shaders/line_sdf.vertex.glsl.txt +20 -0
  49. package/build/min/src/shaders/raster.fragment.glsl.txt +5 -0
  50. package/build/min/src/shaders/raster.vertex.glsl.txt +1 -0
  51. package/build/min/src/shaders/symbol_icon.fragment.glsl.txt +9 -0
  52. package/build/min/src/shaders/symbol_icon.vertex.glsl.txt +5 -0
  53. package/build/min/src/shaders/symbol_sdf.fragment.glsl.txt +19 -0
  54. package/build/min/src/shaders/symbol_sdf.vertex.glsl.txt +13 -0
  55. package/package.json +44 -0
  56. package/src/css/mapbox-gl.css +506 -0
  57. package/src/css/svg/mapboxgl-ctrl-attrib.svg +3 -0
  58. package/src/css/svg/mapboxgl-ctrl-compass.svg +4 -0
  59. package/src/css/svg/mapboxgl-ctrl-fullscreen.svg +3 -0
  60. package/src/css/svg/mapboxgl-ctrl-geolocate-background.svg +3 -0
  61. package/src/css/svg/mapboxgl-ctrl-geolocate.svg +3 -0
  62. package/src/css/svg/mapboxgl-ctrl-logo-compact.svg +2 -0
  63. package/src/css/svg/mapboxgl-ctrl-logo.svg +1 -0
  64. package/src/css/svg/mapboxgl-ctrl-shrink.svg +3 -0
  65. package/src/css/svg/mapboxgl-ctrl-zoom-in.svg +3 -0
  66. package/src/css/svg/mapboxgl-ctrl-zoom-out.svg +3 -0
  67. package/src/data/array_types.js +1138 -0
  68. package/src/data/bucket/circle_attributes.js +5 -0
  69. package/src/data/bucket/circle_bucket.js +118 -0
  70. package/src/data/bucket/fill_attributes.js +5 -0
  71. package/src/data/bucket/fill_bucket.js +166 -0
  72. package/src/data/bucket/fill_extrusion_attributes.js +11 -0
  73. package/src/data/bucket/fill_extrusion_bucket.js +247 -0
  74. package/src/data/bucket/heatmap_bucket.js +12 -0
  75. package/src/data/bucket/line_attributes.js +11 -0
  76. package/src/data/bucket/line_bucket.js +625 -0
  77. package/src/data/bucket/pattern_attributes.js +9 -0
  78. package/src/data/bucket/pattern_bucket_features.js +44 -0
  79. package/src/data/bucket/symbol_attributes.js +95 -0
  80. package/src/data/bucket/symbol_bucket.js +697 -0
  81. package/src/data/bucket.js +53 -0
  82. package/src/data/dem_data.js +126 -0
  83. package/src/data/extent.js +17 -0
  84. package/src/data/feature_index.js +254 -0
  85. package/src/data/index_array_type.js +14 -0
  86. package/src/data/load_geometry.js +42 -0
  87. package/src/data/pos_attributes.js +3 -0
  88. package/src/data/program_configuration.js +782 -0
  89. package/src/data/raster_bounds_attributes.js +6 -0
  90. package/src/data/segment.js +63 -0
  91. package/src/geo/coordinate.js +78 -0
  92. package/src/geo/lng_lat.js +129 -0
  93. package/src/geo/lng_lat_bounds.js +253 -0
  94. package/src/geo/transform.js +605 -0
  95. package/src/gl/color_mode.js +21 -0
  96. package/src/gl/context.js +193 -0
  97. package/src/gl/cull_face_mode.js +22 -0
  98. package/src/gl/depth_mode.js +18 -0
  99. package/src/gl/framebuffer.js +28 -0
  100. package/src/gl/index_buffer.js +52 -0
  101. package/src/gl/stencil_mode.js +17 -0
  102. package/src/gl/types.js +0 -0
  103. package/src/gl/value.js +676 -0
  104. package/src/gl/vertex_buffer.js +101 -0
  105. package/src/index.js +50 -0
  106. package/src/render/draw_background.js +60 -0
  107. package/src/render/draw_circle.js +55 -0
  108. package/src/render/draw_collision_debug.js +45 -0
  109. package/src/render/draw_debug.js +429 -0
  110. package/src/render/draw_fill.js +143 -0
  111. package/src/render/draw_fill_extrusion.js +101 -0
  112. package/src/render/draw_heatmap.js +159 -0
  113. package/src/render/draw_hillshade.js +144 -0
  114. package/src/render/draw_line.js +99 -0
  115. package/src/render/draw_raster.js +151 -0
  116. package/src/render/draw_symbol.js +231 -0
  117. package/src/render/glyph_atlas.js +55 -0
  118. package/src/render/glyph_manager.js +145 -0
  119. package/src/render/image_atlas.js +97 -0
  120. package/src/render/image_manager.js +183 -0
  121. package/src/render/line_atlas.js +139 -0
  122. package/src/render/painter.js +483 -0
  123. package/src/render/program/background_program.js +46 -0
  124. package/src/render/program/circle_program.js +40 -0
  125. package/src/render/program/clipping_mask_program.js +11 -0
  126. package/src/render/program/collision_program.js +28 -0
  127. package/src/render/program/debug_program.js +13 -0
  128. package/src/render/program/fill_extrusion_program.js +76 -0
  129. package/src/render/program/fill_program.js +60 -0
  130. package/src/render/program/heatmap_program.js +46 -0
  131. package/src/render/program/hillshade_program.js +77 -0
  132. package/src/render/program/line_program.js +119 -0
  133. package/src/render/program/pattern.js +57 -0
  134. package/src/render/program/program_uniforms.js +46 -0
  135. package/src/render/program/raster_program.js +50 -0
  136. package/src/render/program/symbol_program.js +112 -0
  137. package/src/render/program.js +133 -0
  138. package/src/render/texture.js +88 -0
  139. package/src/render/tile_mask.js +108 -0
  140. package/src/render/uniform_binding.js +129 -0
  141. package/src/render/vertex_array_object.js +155 -0
  142. package/src/shaders/README.md +42 -0
  143. package/src/shaders/_prelude.fragment.glsl +17 -0
  144. package/src/shaders/_prelude.vertex.glsl +73 -0
  145. package/src/shaders/background.fragment.glsl +10 -0
  146. package/src/shaders/background.vertex.glsl +7 -0
  147. package/src/shaders/background_pattern.fragment.glsl +28 -0
  148. package/src/shaders/background_pattern.vertex.glsl +20 -0
  149. package/src/shaders/circle.fragment.glsl +39 -0
  150. package/src/shaders/circle.vertex.glsl +63 -0
  151. package/src/shaders/clipping_mask.fragment.glsl +3 -0
  152. package/src/shaders/clipping_mask.vertex.glsl +7 -0
  153. package/src/shaders/collision_box.fragment.glsl +21 -0
  154. package/src/shaders/collision_box.vertex.glsl +26 -0
  155. package/src/shaders/collision_circle.fragment.glsl +34 -0
  156. package/src/shaders/collision_circle.vertex.glsl +36 -0
  157. package/src/shaders/debug.fragment.glsl +5 -0
  158. package/src/shaders/debug.vertex.glsl +7 -0
  159. package/src/shaders/encode_attribute.js +19 -0
  160. package/src/shaders/fill.fragment.glsl +13 -0
  161. package/src/shaders/fill.vertex.glsl +13 -0
  162. package/src/shaders/fill_extrusion.fragment.glsl +16 -0
  163. package/src/shaders/fill_extrusion.vertex.glsl +66 -0
  164. package/src/shaders/fill_extrusion_pattern.fragment.glsl +41 -0
  165. package/src/shaders/fill_extrusion_pattern.vertex.glsl +76 -0
  166. package/src/shaders/fill_outline.fragment.glsl +17 -0
  167. package/src/shaders/fill_outline.vertex.glsl +17 -0
  168. package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
  169. package/src/shaders/fill_outline_pattern.vertex.glsl +41 -0
  170. package/src/shaders/fill_pattern.fragment.glsl +36 -0
  171. package/src/shaders/fill_pattern.vertex.glsl +36 -0
  172. package/src/shaders/heatmap.fragment.glsl +21 -0
  173. package/src/shaders/heatmap.vertex.glsl +53 -0
  174. package/src/shaders/heatmap_texture.fragment.glsl +14 -0
  175. package/src/shaders/heatmap_texture.vertex.glsl +11 -0
  176. package/src/shaders/hillshade.fragment.glsl +52 -0
  177. package/src/shaders/hillshade.vertex.glsl +11 -0
  178. package/src/shaders/hillshade_prepare.fragment.glsl +72 -0
  179. package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
  180. package/src/shaders/index.js +194 -0
  181. package/src/shaders/line.fragment.glsl +28 -0
  182. package/src/shaders/line.vertex.glsl +84 -0
  183. package/src/shaders/line_gradient.fragment.glsl +34 -0
  184. package/src/shaders/line_gradient.vertex.glsl +84 -0
  185. package/src/shaders/line_pattern.fragment.glsl +69 -0
  186. package/src/shaders/line_pattern.vertex.glsl +88 -0
  187. package/src/shaders/line_sdf.fragment.glsl +44 -0
  188. package/src/shaders/line_sdf.vertex.glsl +95 -0
  189. package/src/shaders/raster.fragment.glsl +52 -0
  190. package/src/shaders/raster.vertex.glsl +21 -0
  191. package/src/shaders/symbol_icon.fragment.glsl +17 -0
  192. package/src/shaders/symbol_icon.vertex.glsl +91 -0
  193. package/src/shaders/symbol_sdf.fragment.glsl +50 -0
  194. package/src/shaders/symbol_sdf.vertex.glsl +117 -0
  195. package/src/source/geojson_source.js +267 -0
  196. package/src/source/geojson_worker_source.js +210 -0
  197. package/src/source/geojson_wrapper.js +67 -0
  198. package/src/source/image_source.js +213 -0
  199. package/src/source/load_tilejson.js +40 -0
  200. package/src/source/pixels_to_tile_units.js +17 -0
  201. package/src/source/query_features.js +198 -0
  202. package/src/source/raster_dem_tile_source.js +140 -0
  203. package/src/source/raster_dem_tile_worker_source.js +26 -0
  204. package/src/source/raster_tile_source.js +126 -0
  205. package/src/source/rtl_text_plugin.js +63 -0
  206. package/src/source/source.js +75 -0
  207. package/src/source/source_cache.js +794 -0
  208. package/src/source/source_state.js +55 -0
  209. package/src/source/tile.js +332 -0
  210. package/src/source/tile_bounds.js +40 -0
  211. package/src/source/tile_cache.js +122 -0
  212. package/src/source/tile_id.js +150 -0
  213. package/src/source/vector_tile_source.js +144 -0
  214. package/src/source/vector_tile_worker_source.js +126 -0
  215. package/src/source/worker.js +175 -0
  216. package/src/source/worker_source.js +14 -0
  217. package/src/source/worker_tile.js +199 -0
  218. package/src/style/create_style_layer.js +25 -0
  219. package/src/style/evaluation_parameters.js +45 -0
  220. package/src/style/light.js +112 -0
  221. package/src/style/load_glyph_range.js +17 -0
  222. package/src/style/load_sprite.js +26 -0
  223. package/src/style/parse_glyph_pbf.js +45 -0
  224. package/src/style/pauseable_placement.js +88 -0
  225. package/src/style/properties.js +691 -0
  226. package/src/style/query_utils.js +39 -0
  227. package/src/style/style.js +955 -0
  228. package/src/style/style_layer/background_style_layer.js +11 -0
  229. package/src/style/style_layer/background_style_layer_properties.js +25 -0
  230. package/src/style/style_layer/circle_style_layer.js +93 -0
  231. package/src/style/style_layer/circle_style_layer_properties.js +76 -0
  232. package/src/style/style_layer/fill_extrusion_style_layer.js +194 -0
  233. package/src/style/style_layer/fill_extrusion_style_layer_properties.js +56 -0
  234. package/src/style/style_layer/fill_style_layer.js +46 -0
  235. package/src/style/style_layer/fill_style_layer_properties.js +45 -0
  236. package/src/style/style_layer/heatmap_style_layer.js +51 -0
  237. package/src/style/style_layer/heatmap_style_layer_properties.js +52 -0
  238. package/src/style/style_layer/hillshade_style_layer.js +15 -0
  239. package/src/style/style_layer/hillshade_style_layer_properties.js +43 -0
  240. package/src/style/style_layer/line_style_layer.js +129 -0
  241. package/src/style/style_layer/line_style_layer_properties.js +104 -0
  242. package/src/style/style_layer/raster_style_layer.js +11 -0
  243. package/src/style/style_layer/raster_style_layer_properties.js +55 -0
  244. package/src/style/style_layer/symbol_style_layer.js +66 -0
  245. package/src/style/style_layer/symbol_style_layer_properties.js +288 -0
  246. package/src/style/style_layer.js +183 -0
  247. package/src/style/style_layer_index.js +61 -0
  248. package/src/style/zoom_history.js +36 -0
  249. package/src/style-spec/deref.js +51 -0
  250. package/src/style-spec/error/parsing_error.js +8 -0
  251. package/src/style-spec/error/validation_error.js +10 -0
  252. package/src/style-spec/expression/compound_expression.js +118 -0
  253. package/src/style-spec/expression/definitions/array.js +82 -0
  254. package/src/style-spec/expression/definitions/assertion.js +69 -0
  255. package/src/style-spec/expression/definitions/at.js +57 -0
  256. package/src/style-spec/expression/definitions/case.js +73 -0
  257. package/src/style-spec/expression/definitions/coalesce.js +68 -0
  258. package/src/style-spec/expression/definitions/coercion.js +96 -0
  259. package/src/style-spec/expression/definitions/collator.js +102 -0
  260. package/src/style-spec/expression/definitions/equals.js +93 -0
  261. package/src/style-spec/expression/definitions/index.js +407 -0
  262. package/src/style-spec/expression/definitions/interpolate.js +235 -0
  263. package/src/style-spec/expression/definitions/length.js +54 -0
  264. package/src/style-spec/expression/definitions/let.js +60 -0
  265. package/src/style-spec/expression/definitions/literal.js +64 -0
  266. package/src/style-spec/expression/definitions/match.js +142 -0
  267. package/src/style-spec/expression/definitions/step.js +116 -0
  268. package/src/style-spec/expression/definitions/var.js +38 -0
  269. package/src/style-spec/expression/evaluation_context.js +35 -0
  270. package/src/style-spec/expression/index.js +329 -0
  271. package/src/style-spec/expression/is_constant.js +63 -0
  272. package/src/style-spec/expression/parsing_context.js +213 -0
  273. package/src/style-spec/expression/parsing_error.js +9 -0
  274. package/src/style-spec/expression/runtime_error.js +12 -0
  275. package/src/style-spec/expression/scope.js +34 -0
  276. package/src/style-spec/expression/stops.js +37 -0
  277. package/src/style-spec/expression/types.js +77 -0
  278. package/src/style-spec/expression/values.js +126 -0
  279. package/src/style-spec/feature_filter/README.md +55 -0
  280. package/src/style-spec/feature_filter/index.js +158 -0
  281. package/src/style-spec/function/convert.js +256 -0
  282. package/src/style-spec/function/index.js +299 -0
  283. package/src/style-spec/group_by_layout.js +68 -0
  284. package/src/style-spec/reference/v8.json +5356 -0
  285. package/src/style-spec/util/color.js +73 -0
  286. package/src/style-spec/util/color_spaces.js +128 -0
  287. package/src/style-spec/util/eval_support.js +8 -0
  288. package/src/style-spec/util/get_type.js +18 -0
  289. package/src/style-spec/util/interpolate.js +21 -0
  290. package/src/style-spec/util/properties.js +17 -0
  291. package/src/style-spec/util/ref_properties.js +1 -0
  292. package/src/style-spec/util/result.js +19 -0
  293. package/src/symbol/anchor.js +21 -0
  294. package/src/symbol/check_max_angle.js +75 -0
  295. package/src/symbol/clip_line.js +73 -0
  296. package/src/symbol/collision_feature.js +230 -0
  297. package/src/symbol/collision_index.js +379 -0
  298. package/src/symbol/cross_tile_symbol_index.js +270 -0
  299. package/src/symbol/get_anchors.js +177 -0
  300. package/src/symbol/grid_index.js +318 -0
  301. package/src/symbol/mergelines.js +75 -0
  302. package/src/symbol/opacity_state.js +21 -0
  303. package/src/symbol/placement.js +563 -0
  304. package/src/symbol/projection.js +601 -0
  305. package/src/symbol/quads.js +173 -0
  306. package/src/symbol/shaping.js +347 -0
  307. package/src/symbol/symbol_layout.js +519 -0
  308. package/src/symbol/symbol_size.js +110 -0
  309. package/src/symbol/transform_text.js +16 -0
  310. package/src/ui/anchor.js +24 -0
  311. package/src/ui/bind_handlers.js +199 -0
  312. package/src/ui/camera.js +954 -0
  313. package/src/ui/events.js +210 -0
  314. package/src/ui/handler/box_zoom.js +151 -0
  315. package/src/ui/handler/dblclick_zoom.js +91 -0
  316. package/src/ui/handler/drag_pan.js +285 -0
  317. package/src/ui/handler/drag_rotate.js +290 -0
  318. package/src/ui/handler/frame.js +28 -0
  319. package/src/ui/handler/inertia.js +45 -0
  320. package/src/ui/handler/keyboard.js +148 -0
  321. package/src/ui/handler/scroll_zoom.js +284 -0
  322. package/src/ui/handler/touch_zoom_rotate.js +263 -0
  323. package/src/ui/map.js +1645 -0
  324. package/src/util/actor.js +104 -0
  325. package/src/util/async.js +23 -0
  326. package/src/util/browser.js +61 -0
  327. package/src/util/callback.js +26 -0
  328. package/src/util/classify_rings.js +43 -0
  329. package/src/util/color_ramp.js +24 -0
  330. package/src/util/config.js +24 -0
  331. package/src/util/dictionary_coder.js +25 -0
  332. package/src/util/dispatcher.js +68 -0
  333. package/src/util/dom.js +102 -0
  334. package/src/util/evented.js +182 -0
  335. package/src/util/find_pole_of_inaccessibility.js +129 -0
  336. package/src/util/global_worker_pool.js +15 -0
  337. package/src/util/image.js +124 -0
  338. package/src/util/interpolate.js +5 -0
  339. package/src/util/intersection_tests.js +207 -0
  340. package/src/util/is_char_in_unicode_block.js +287 -0
  341. package/src/util/loader/image.js +32 -0
  342. package/src/util/object.js +178 -0
  343. package/src/util/script_detection.js +337 -0
  344. package/src/util/struct_array.js +197 -0
  345. package/src/util/task_queue.js +57 -0
  346. package/src/util/throttle.js +26 -0
  347. package/src/util/tile_cover.js +114 -0
  348. package/src/util/token.js +13 -0
  349. package/src/util/unique_id.js +12 -0
  350. package/src/util/util.js +192 -0
  351. package/src/util/vectortile_to_geojson.js +44 -0
  352. package/src/util/verticalize_punctuation.js +112 -0
  353. package/src/util/warn.js +21 -0
  354. package/src/util/web_worker.js +5 -0
  355. package/src/util/web_worker_transfer.js +228 -0
  356. package/src/util/worker_pool.js +41 -0
@@ -0,0 +1,337 @@
1
+ const isChar = require('./is_char_in_unicode_block');
2
+
3
+ module.exports = {
4
+ allowsIdeographicBreaking,
5
+ allowsVerticalWritingMode,
6
+ allowsLetterSpacing,
7
+ charAllowsLetterSpacing,
8
+ charAllowsIdeographicBreaking,
9
+ charHasUprightVerticalOrientation,
10
+ charHasNeutralVerticalOrientation,
11
+ charHasRotatedVerticalOrientation,
12
+ charInSupportedScript,
13
+ isStringInSupportedScript
14
+ };
15
+
16
+ function allowsIdeographicBreaking(chars) {
17
+ for (const char of chars) {
18
+ if (!charAllowsIdeographicBreaking(char.charCodeAt(0))) return false;
19
+ }
20
+ return true;
21
+ }
22
+
23
+ function allowsVerticalWritingMode(chars) {
24
+ for (const char of chars) {
25
+ if (charHasUprightVerticalOrientation(char.charCodeAt(0))) return true;
26
+ }
27
+ return false;
28
+ }
29
+
30
+ function allowsLetterSpacing(chars) {
31
+ for (const char of chars) {
32
+ if (!charAllowsLetterSpacing(char.charCodeAt(0))) return false;
33
+ }
34
+ return true;
35
+ }
36
+
37
+ function charAllowsLetterSpacing(char) {
38
+ if (isChar['Arabic'](char)) return false;
39
+ if (isChar['Arabic Supplement'](char)) return false;
40
+ if (isChar['Arabic Extended-A'](char)) return false;
41
+ if (isChar['Arabic Presentation Forms-A'](char)) return false;
42
+ if (isChar['Arabic Presentation Forms-B'](char)) return false;
43
+
44
+ return true;
45
+ }
46
+
47
+ function charAllowsIdeographicBreaking(char) {
48
+ // Return early for characters outside all ideographic ranges.
49
+ if (char < 0x2e80) return false;
50
+
51
+ if (isChar['Bopomofo Extended'](char)) return true;
52
+ if (isChar['Bopomofo'](char)) return true;
53
+ if (isChar['CJK Compatibility Forms'](char)) return true;
54
+ if (isChar['CJK Compatibility Ideographs'](char)) return true;
55
+ if (isChar['CJK Compatibility'](char)) return true;
56
+ if (isChar['CJK Radicals Supplement'](char)) return true;
57
+ if (isChar['CJK Strokes'](char)) return true;
58
+ if (isChar['CJK Symbols and Punctuation'](char)) return true;
59
+ if (isChar['CJK Unified Ideographs Extension A'](char)) return true;
60
+ if (isChar['CJK Unified Ideographs'](char)) return true;
61
+ if (isChar['Enclosed CJK Letters and Months'](char)) return true;
62
+ if (isChar['Halfwidth and Fullwidth Forms'](char)) return true;
63
+ if (isChar['Hiragana'](char)) return true;
64
+ if (isChar['Ideographic Description Characters'](char)) return true;
65
+ if (isChar['Kangxi Radicals'](char)) return true;
66
+ if (isChar['Katakana Phonetic Extensions'](char)) return true;
67
+ if (isChar['Katakana'](char)) return true;
68
+ if (isChar['Vertical Forms'](char)) return true;
69
+ if (isChar['Yi Radicals'](char)) return true;
70
+ if (isChar['Yi Syllables'](char)) return true;
71
+
72
+ return false;
73
+ }
74
+
75
+ // The following logic comes from
76
+ // <http://www.unicode.org/Public/vertical/revision-17/VerticalOrientation-17.txt>.
77
+ // The data file denotes with “U” or “Tu” any codepoint that may be drawn
78
+ // upright in vertical text but does not distinguish between upright and
79
+ // “neutral” characters.
80
+
81
+ // Blocks in the Unicode supplementary planes are excluded from this module due
82
+ // to <https://github.com/mapbox/mapbox-gl/issues/29>.
83
+
84
+ /**
85
+ * Returns true if the given Unicode codepoint identifies a character with
86
+ * upright orientation.
87
+ *
88
+ * A character has upright orientation if it is drawn upright (unrotated)
89
+ * whether the line is oriented horizontally or vertically, even if both
90
+ * adjacent characters can be rotated. For example, a Chinese character is
91
+ * always drawn upright. An uprightly oriented character causes an adjacent
92
+ * “neutral” character to be drawn upright as well.
93
+ * @private
94
+ */
95
+ function charHasUprightVerticalOrientation(char) {
96
+ if (
97
+ char === 0x02ea /* modifier letter yin departing tone mark */ ||
98
+ char === 0x02eb /* modifier letter yang departing tone mark */
99
+ ) {
100
+ return true;
101
+ }
102
+
103
+ // Return early for characters outside all ranges whose characters remain
104
+ // upright in vertical writing mode.
105
+ if (char < 0x1100) return false;
106
+
107
+ if (isChar['Bopomofo Extended'](char)) return true;
108
+ if (isChar['Bopomofo'](char)) return true;
109
+ if (isChar['CJK Compatibility Forms'](char)) {
110
+ if (!((char >= 0xfe49 /* dashed overline */ && char <= 0xfe4f) /* wavy low line */)) {
111
+ return true;
112
+ }
113
+ }
114
+ if (isChar['CJK Compatibility Ideographs'](char)) return true;
115
+ if (isChar['CJK Compatibility'](char)) return true;
116
+ if (isChar['CJK Radicals Supplement'](char)) return true;
117
+ if (isChar['CJK Strokes'](char)) return true;
118
+ if (isChar['CJK Symbols and Punctuation'](char)) {
119
+ if (
120
+ !((char >= 0x3008 /* left angle bracket */ && char <= 0x3011) /* right black lenticular bracket */) &&
121
+ !((char >= 0x3014 /* left tortoise shell bracket */ && char <= 0x301f) /* low double prime quotation mark */) &&
122
+ char !== 0x3030 /* wavy dash */
123
+ ) {
124
+ return true;
125
+ }
126
+ }
127
+ if (isChar['CJK Unified Ideographs Extension A'](char)) return true;
128
+ if (isChar['CJK Unified Ideographs'](char)) return true;
129
+ if (isChar['Enclosed CJK Letters and Months'](char)) return true;
130
+ if (isChar['Hangul Compatibility Jamo'](char)) return true;
131
+ if (isChar['Hangul Jamo Extended-A'](char)) return true;
132
+ if (isChar['Hangul Jamo Extended-B'](char)) return true;
133
+ if (isChar['Hangul Jamo'](char)) return true;
134
+ if (isChar['Hangul Syllables'](char)) return true;
135
+ if (isChar['Hiragana'](char)) return true;
136
+ if (isChar['Ideographic Description Characters'](char)) return true;
137
+ if (isChar['Kanbun'](char)) return true;
138
+ if (isChar['Kangxi Radicals'](char)) return true;
139
+ if (isChar['Katakana Phonetic Extensions'](char)) return true;
140
+ if (isChar['Katakana'](char)) {
141
+ if (char !== 0x30fc /* katakana-hiragana prolonged sound mark */) {
142
+ return true;
143
+ }
144
+ }
145
+ if (isChar['Halfwidth and Fullwidth Forms'](char)) {
146
+ if (
147
+ char !== 0xff08 /* fullwidth left parenthesis */ &&
148
+ char !== 0xff09 /* fullwidth right parenthesis */ &&
149
+ char !== 0xff0d /* fullwidth hyphen-minus */ &&
150
+ !((char >= 0xff1a /* fullwidth colon */ && char <= 0xff1e) /* fullwidth greater-than sign */) &&
151
+ char !== 0xff3b /* fullwidth left square bracket */ &&
152
+ char !== 0xff3d /* fullwidth right square bracket */ &&
153
+ char !== 0xff3f /* fullwidth low line */ &&
154
+ !(char >= 0xff5b /* fullwidth left curly bracket */ && char <= 0xffdf) &&
155
+ char !== 0xffe3 /* fullwidth macron */ &&
156
+ !(char >= 0xffe8 /* halfwidth forms light vertical */ && char <= 0xffef)
157
+ ) {
158
+ return true;
159
+ }
160
+ }
161
+ if (isChar['Small Form Variants'](char)) {
162
+ if (
163
+ !((char >= 0xfe58 /* small em dash */ && char <= 0xfe5e) /* small right tortoise shell bracket */) &&
164
+ !((char >= 0xfe63 /* small hyphen-minus */ && char <= 0xfe66) /* small equals sign */)
165
+ ) {
166
+ return true;
167
+ }
168
+ }
169
+ if (isChar['Unified Canadian Aboriginal Syllabics'](char)) return true;
170
+ if (isChar['Unified Canadian Aboriginal Syllabics Extended'](char)) return true;
171
+ if (isChar['Vertical Forms'](char)) return true;
172
+ if (isChar['Yijing Hexagram Symbols'](char)) return true;
173
+ if (isChar['Yi Syllables'](char)) return true;
174
+ if (isChar['Yi Radicals'](char)) return true;
175
+
176
+ return false;
177
+ }
178
+
179
+ /**
180
+ * Returns true if the given Unicode codepoint identifies a character with
181
+ * neutral orientation.
182
+ *
183
+ * A character has neutral orientation if it may be drawn rotated or unrotated
184
+ * when the line is oriented vertically, depending on the orientation of the
185
+ * adjacent characters. For example, along a verticlly oriented line, the vulgar
186
+ * fraction ½ is drawn upright among Chinese characters but rotated among Latin
187
+ * letters. A neutrally oriented character does not influence whether an
188
+ * adjacent character is drawn upright or rotated.
189
+ * @private
190
+ */
191
+ function charHasNeutralVerticalOrientation(char) {
192
+ if (isChar['Latin-1 Supplement'](char)) {
193
+ if (
194
+ char === 0x00a7 /* section sign */ ||
195
+ char === 0x00a9 /* copyright sign */ ||
196
+ char === 0x00ae /* registered sign */ ||
197
+ char === 0x00b1 /* plus-minus sign */ ||
198
+ char === 0x00bc /* vulgar fraction one quarter */ ||
199
+ char === 0x00bd /* vulgar fraction one half */ ||
200
+ char === 0x00be /* vulgar fraction three quarters */ ||
201
+ char === 0x00d7 /* multiplication sign */ ||
202
+ char === 0x00f7 /* division sign */
203
+ ) {
204
+ return true;
205
+ }
206
+ }
207
+ if (isChar['General Punctuation'](char)) {
208
+ if (
209
+ char === 0x2016 /* double vertical line */ ||
210
+ char === 0x2020 /* dagger */ ||
211
+ char === 0x2021 /* double dagger */ ||
212
+ char === 0x2030 /* per mille sign */ ||
213
+ char === 0x2031 /* per ten thousand sign */ ||
214
+ char === 0x203b /* reference mark */ ||
215
+ char === 0x203c /* double exclamation mark */ ||
216
+ char === 0x2042 /* asterism */ ||
217
+ char === 0x2047 /* double question mark */ ||
218
+ char === 0x2048 /* question exclamation mark */ ||
219
+ char === 0x2049 /* exclamation question mark */ ||
220
+ char === 0x2051 /* two asterisks aligned vertically */
221
+ ) {
222
+ return true;
223
+ }
224
+ }
225
+ if (isChar['Letterlike Symbols'](char)) return true;
226
+ if (isChar['Number Forms'](char)) return true;
227
+ if (isChar['Miscellaneous Technical'](char)) {
228
+ if (
229
+ (char >= 0x2300 /* diameter sign */ && char <= 0x2307) /* wavy line */ ||
230
+ (char >= 0x230c /* bottom right crop */ && char <= 0x231f) /* bottom right corner */ ||
231
+ (char >= 0x2324 /* up arrowhead between two horizontal bars */ && char <= 0x2328) /* keyboard */ ||
232
+ char === 0x232b /* erase to the left */ ||
233
+ (char >= 0x237d /* shouldered open box */ && char <= 0x239a) /* clear screen symbol */ ||
234
+ (char >= 0x23be /* dentistry symbol light vertical and top right */ && char <= 0x23cd) /* square foot */ ||
235
+ char === 0x23cf /* eject symbol */ ||
236
+ (char >= 0x23d1 /* metrical breve */ && char <= 0x23db) /* fuse */ ||
237
+ (char >= 0x23e2 /* white trapezium */ && char <= 0x23ff)
238
+ ) {
239
+ return true;
240
+ }
241
+ }
242
+ if (isChar['Control Pictures'](char) && char !== 0x2423 /* open box */) return true;
243
+ if (isChar['Optical Character Recognition'](char)) return true;
244
+ if (isChar['Enclosed Alphanumerics'](char)) return true;
245
+ if (isChar['Geometric Shapes'](char)) return true;
246
+ if (isChar['Miscellaneous Symbols'](char)) {
247
+ if (!((char >= 0x261a /* black left pointing index */ && char <= 0x261f) /* white down pointing index */)) {
248
+ return true;
249
+ }
250
+ }
251
+ if (isChar['Miscellaneous Symbols and Arrows'](char)) {
252
+ if (
253
+ (char >= 0x2b12 /* square with top half black */ && char <= 0x2b2f) /* white vertical ellipse */ ||
254
+ (char >= 0x2b50 /* white medium star */ && char <= 0x2b59) /* heavy circled saltire */ ||
255
+ (char >= 0x2bb8 /* upwards white arrow from bar with horizontal bar */ && char <= 0x2beb)
256
+ ) {
257
+ return true;
258
+ }
259
+ }
260
+ if (isChar['CJK Symbols and Punctuation'](char)) return true;
261
+ if (isChar['Katakana'](char)) return true;
262
+ if (isChar['Private Use Area'](char)) return true;
263
+ if (isChar['CJK Compatibility Forms'](char)) return true;
264
+ if (isChar['Small Form Variants'](char)) return true;
265
+ if (isChar['Halfwidth and Fullwidth Forms'](char)) return true;
266
+
267
+ if (
268
+ char === 0x221e /* infinity */ ||
269
+ char === 0x2234 /* therefore */ ||
270
+ char === 0x2235 /* because */ ||
271
+ (char >= 0x2700 /* black safety scissors */ && char <= 0x2767) /* rotated floral heart bullet */ ||
272
+ (char >= 0x2776 /* dingbat negative circled digit one */ &&
273
+ char <= 0x2793) /* dingbat negative circled sans-serif number ten */ ||
274
+ char === 0xfffc /* object replacement character */ ||
275
+ char === 0xfffd /* replacement character */
276
+ ) {
277
+ return true;
278
+ }
279
+
280
+ return false;
281
+ }
282
+
283
+ /**
284
+ * Returns true if the given Unicode codepoint identifies a character with
285
+ * rotated orientation.
286
+ *
287
+ * A character has rotated orientation if it is drawn rotated when the line is
288
+ * oriented vertically, even if both adjacent characters are upright. For
289
+ * example, a Latin letter is drawn rotated along a vertical line. A rotated
290
+ * character causes an adjacent “neutral” character to be drawn rotated as well.
291
+ * @private
292
+ */
293
+ function charHasRotatedVerticalOrientation(char) {
294
+ return !(charHasUprightVerticalOrientation(char) || charHasNeutralVerticalOrientation(char));
295
+ }
296
+
297
+ function charInSupportedScript(char, canRenderRTL) {
298
+ // This is a rough heuristic: whether we "can render" a script
299
+ // actually depends on the properties of the font being used
300
+ // and whether differences from the ideal rendering are considered
301
+ // semantically significant.
302
+
303
+ // Even in Latin script, we "can't render" combinations such as the fi
304
+ // ligature, but we don't consider that semantically significant.
305
+ if (
306
+ !canRenderRTL &&
307
+ ((char >= 0x0590 && char <= 0x08ff) ||
308
+ isChar['Arabic Presentation Forms-A'](char) ||
309
+ isChar['Arabic Presentation Forms-B'](char))
310
+ ) {
311
+ // Main blocks for Hebrew, Arabic, Thaana and other RTL scripts
312
+ return false;
313
+ }
314
+ if (
315
+ (char >= 0x0900 && char <= 0x0dff) ||
316
+ // Main blocks for Indic scripts and Sinhala
317
+ (char >= 0x0f00 && char <= 0x109f) ||
318
+ // Main blocks for Tibetan and Myanmar
319
+ isChar['Khmer'](char)
320
+ ) {
321
+ // These blocks cover common scripts that require
322
+ // complex text shaping, based on unicode script metadata:
323
+ // http://www.unicode.org/repos/cldr/trunk/common/properties/scriptMetadata.txt
324
+ // where "Web Rank <= 32" "Shaping Required = YES"
325
+ return false;
326
+ }
327
+ return true;
328
+ }
329
+
330
+ function isStringInSupportedScript(chars, canRenderRTL) {
331
+ for (const char of chars) {
332
+ if (!charInSupportedScript(char.charCodeAt(0), canRenderRTL)) {
333
+ return false;
334
+ }
335
+ }
336
+ return true;
337
+ }
@@ -0,0 +1,197 @@
1
+ // Note: all "sizes" are measured in bytes
2
+
3
+ const assert = require('assert');
4
+
5
+ const viewTypes = {
6
+ Int8: Int8Array,
7
+ Uint8: Uint8Array,
8
+ Int16: Int16Array,
9
+ Uint16: Uint16Array,
10
+ Int32: Int32Array,
11
+ Uint32: Uint32Array,
12
+ Float32: Float32Array
13
+ };
14
+
15
+ /**
16
+ * @private
17
+ */
18
+ class Struct {
19
+ // The following properties are defined on the prototype of sub classes.
20
+
21
+ /**
22
+ * @param {StructArray} structArray The StructArray the struct is stored in
23
+ * @param {number} index The index of the struct in the StructArray.
24
+ * @private
25
+ */
26
+ constructor(structArray, index) {
27
+ this._structArray = structArray;
28
+ this._pos1 = index * this.size;
29
+ this._pos2 = this._pos1 / 2;
30
+ this._pos4 = this._pos1 / 4;
31
+ this._pos8 = this._pos1 / 8;
32
+ }
33
+ }
34
+
35
+ const DEFAULT_CAPACITY = 128;
36
+ const RESIZE_MULTIPLIER = 5;
37
+
38
+ /**
39
+ * `StructArray` provides an abstraction over `ArrayBuffer` and `TypedArray`
40
+ * making it behave like an array of typed structs.
41
+ *
42
+ * Conceptually, a StructArray is comprised of elements, i.e., instances of its
43
+ * associated struct type. Each particular struct type, together with an
44
+ * alignment size, determines the memory layout of a StructArray whose elements
45
+ * are of that type. Thus, for each such layout that we need, we have
46
+ * a corrseponding StructArrayLayout class, inheriting from StructArray and
47
+ * implementing `emplaceBack()` and `_refreshViews()`.
48
+ *
49
+ * In some cases, where we need to access particular elements of a StructArray,
50
+ * we implement a more specific subclass that inherits from one of the
51
+ * StructArrayLayouts and adds a `get(i): T` accessor that returns a structured
52
+ * object whose properties are proxies into the underlying memory space for the
53
+ * i-th element. This affords the convience of working with (seemingly) plain
54
+ * Javascript objects without the overhead of serializing/deserializing them
55
+ * into ArrayBuffers for efficient web worker transfer.
56
+ *
57
+ * @private
58
+ */
59
+ class StructArray {
60
+ // The following properties are defined on the prototype.
61
+
62
+ constructor() {
63
+ this.isTransferred = false;
64
+ this.capacity = -1;
65
+ this.resize(0);
66
+ }
67
+
68
+ /**
69
+ * Serialize a StructArray instance. Serializes both the raw data and the
70
+ * metadata needed to reconstruct the StructArray base class during
71
+ * deserialization.
72
+ */
73
+ static serialize(array, transferables) {
74
+ assert(!array.isTransferred);
75
+
76
+ array._trim();
77
+
78
+ if (transferables) {
79
+ array.isTransferred = true;
80
+ transferables.push(array.arrayBuffer);
81
+ }
82
+
83
+ return {
84
+ length: array.length,
85
+ arrayBuffer: array.arrayBuffer
86
+ };
87
+ }
88
+
89
+ static deserialize(input) {
90
+ const structArray = Object.create(this.prototype);
91
+ structArray.arrayBuffer = input.arrayBuffer;
92
+ structArray.length = input.length;
93
+ structArray.capacity = input.arrayBuffer.byteLength / structArray.bytesPerElement;
94
+ structArray._refreshViews();
95
+ return structArray;
96
+ }
97
+
98
+ /**
99
+ * Resize the array to discard unused capacity.
100
+ */
101
+ _trim() {
102
+ if (this.length !== this.capacity) {
103
+ this.capacity = this.length;
104
+ this.arrayBuffer = this.arrayBuffer.slice(0, this.length * this.bytesPerElement);
105
+ this._refreshViews();
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Resets the the length of the array to 0 without de-allocating capcacity.
111
+ */
112
+ clear() {
113
+ this.length = 0;
114
+ }
115
+
116
+ /**
117
+ * Resize the array.
118
+ * If `n` is greater than the current length then additional elements with undefined values are added.
119
+ * If `n` is less than the current length then the array will be reduced to the first `n` elements.
120
+ * @param {number} n The new size of the array.
121
+ */
122
+ resize(n) {
123
+ assert(!this.isTransferred);
124
+ this.reserve(n);
125
+ this.length = n;
126
+ }
127
+
128
+ /**
129
+ * Indicate a planned increase in size, so that any necessary allocation may
130
+ * be done once, ahead of time.
131
+ * @param {number} n The expected size of the array.
132
+ */
133
+ reserve(n) {
134
+ if (n > this.capacity) {
135
+ this.capacity = Math.max(n, Math.floor(this.capacity * RESIZE_MULTIPLIER), DEFAULT_CAPACITY);
136
+ this.arrayBuffer = new ArrayBuffer(this.capacity * this.bytesPerElement);
137
+
138
+ const oldUint8Array = this.uint8;
139
+ this._refreshViews();
140
+ if (oldUint8Array) this.uint8.set(oldUint8Array);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Create TypedArray views for the current ArrayBuffer.
146
+ */
147
+ _refreshViews() {
148
+ throw new Error('_refreshViews() must be implemented by each concrete StructArray layout');
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Given a list of member fields, create a full StructArrayLayout, in
154
+ * particular calculating the correct byte offset for each field. This data
155
+ * is used at build time to generate StructArrayLayout_*#emplaceBack() and
156
+ * other accessors, and at runtime for binding vertex buffer attributes.
157
+ *
158
+ * @private
159
+ */
160
+ function createLayout(members, alignment = 1) {
161
+ let offset = 0;
162
+ let maxSize = 0;
163
+ const layoutMembers = members.map(member => {
164
+ assert(member.name.length);
165
+ const typeSize = sizeOf(member.type);
166
+ const memberOffset = (offset = align(offset, Math.max(alignment, typeSize)));
167
+ const components = member.components || 1;
168
+
169
+ maxSize = Math.max(maxSize, typeSize);
170
+ offset += typeSize * components;
171
+
172
+ return {
173
+ name: member.name,
174
+ type: member.type,
175
+ components: components,
176
+ offset: memberOffset
177
+ };
178
+ });
179
+
180
+ const size = align(offset, Math.max(maxSize, alignment));
181
+
182
+ return {
183
+ members: layoutMembers,
184
+ size,
185
+ alignment
186
+ };
187
+ }
188
+
189
+ function sizeOf(type) {
190
+ return viewTypes[type].BYTES_PER_ELEMENT;
191
+ }
192
+
193
+ function align(offset, size) {
194
+ return Math.ceil(offset / size) * size;
195
+ }
196
+
197
+ module.exports = { StructArray, Struct, viewTypes, createLayout };
@@ -0,0 +1,57 @@
1
+ const assert = require('assert');
2
+
3
+ // can't mark opaque due to https://github.com/flowtype/flow-remove-types/pull/61
4
+
5
+ class TaskQueue {
6
+ constructor() {
7
+ this._queue = [];
8
+ this._id = 0;
9
+ this._cleared = false;
10
+ this._currentlyRunning = false;
11
+ }
12
+
13
+ add(callback) {
14
+ const id = ++this._id;
15
+ const queue = this._queue;
16
+ queue.push({ callback, id, cancelled: false });
17
+ return id;
18
+ }
19
+
20
+ remove(id) {
21
+ const running = this._currentlyRunning;
22
+ const queue = running ? this._queue.concat(running) : this._queue;
23
+ for (const task of queue) {
24
+ if (task.id === id) {
25
+ task.cancelled = true;
26
+ return;
27
+ }
28
+ }
29
+ }
30
+
31
+ run() {
32
+ assert(!this._currentlyRunning);
33
+ const queue = (this._currentlyRunning = this._queue);
34
+
35
+ // Tasks queued by callbacks in the current queue should be executed
36
+ // on the next run, not the current run.
37
+ this._queue = [];
38
+
39
+ for (const task of queue) {
40
+ if (task.cancelled) continue;
41
+ task.callback();
42
+ if (this._cleared) break;
43
+ }
44
+
45
+ this._cleared = false;
46
+ this._currentlyRunning = false;
47
+ }
48
+
49
+ clear() {
50
+ if (this._currentlyRunning) {
51
+ this._cleared = true;
52
+ }
53
+ this._queue = [];
54
+ }
55
+ }
56
+
57
+ module.exports = TaskQueue;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Throttle the given function to run at most every `period` milliseconds.
3
+ Throttle the given function to run at most every period milliseconds.
4
+ * @private
5
+ */
6
+ module.exports = function throttle(fn, time) {
7
+ let pending = false;
8
+ let timerId = 0;
9
+
10
+ const later = () => {
11
+ timerId = 0;
12
+ if (pending) {
13
+ fn();
14
+ timerId = setTimeout(later, time);
15
+ pending = false;
16
+ }
17
+ };
18
+
19
+ return () => {
20
+ pending = true;
21
+ if (!timerId) {
22
+ later();
23
+ }
24
+ return timerId;
25
+ };
26
+ };