import { create as create2, fromTransform } from "./chunk-L47B4DRW.js"; import { DataTile_default, LRUCache_default, asArrayLike, asImageLike } from "./chunk-FPVJKBJO.js"; import { Tile_default } from "./chunk-QL7JR4NF.js"; import { createOrUpdate, getKey } from "./chunk-SQ4UGRSZ.js"; import { ImageTile_default } from "./chunk-MESSQWK4.js"; import { TileRange_default } from "./chunk-LRXO5GLT.js"; import { Layer_default } from "./chunk-C66424RK.js"; import { TileState_default } from "./chunk-5D2XPBR2.js"; import { BooleanType, CallExpression, ColorType, NumberArrayType, NumberType, Ops, SizeType, StringType, newParsingContext, parse, typeName } from "./chunk-E5F6ZCFZ.js"; import { EventType_default as EventType_default2, Event_default, Property_default } from "./chunk-S5OMZ56B.js"; import { asArray } from "./chunk-GMHZLYJW.js"; import { toSize } from "./chunk-PPP4FLHO.js"; import { createCanvasContext2D } from "./chunk-YWIWRQT2.js"; import { SAFARI_BUG_237906 } from "./chunk-5XHD7RSF.js"; import { apply, compose, create, reset, rotate, scale, translate } from "./chunk-JFONEOYG.js"; import { fromUserExtent } from "./chunk-XZU4LSFD.js"; import { boundingExtent, containsCoordinate, getIntersection, getRotatedViewport, isEmpty } from "./chunk-CKDBVGKM.js"; import { assert } from "./chunk-QFCIXVZ3.js"; import { abstract, getUid } from "./chunk-H47PV7W6.js"; import { Disposable_default, EventType_default, Target_default } from "./chunk-KJXIHBKT.js"; import { descending } from "./chunk-FQY6EMA7.js"; import { clear } from "./chunk-5RHQVMYD.js"; // node_modules/ol/webgl.js var ARRAY_BUFFER = 34962; var ELEMENT_ARRAY_BUFFER = 34963; var STREAM_DRAW = 35040; var STATIC_DRAW = 35044; var DYNAMIC_DRAW = 35048; var UNSIGNED_BYTE = 5121; var UNSIGNED_SHORT = 5123; var UNSIGNED_INT = 5125; var FLOAT = 5126; var CONTEXT_IDS = ["experimental-webgl", "webgl", "webkit-3d", "moz-webgl"]; function getContext(canvas, attributes) { attributes = Object.assign( { preserveDrawingBuffer: true, antialias: SAFARI_BUG_237906 ? false : true // https://bugs.webkit.org/show_bug.cgi?id=237906 }, attributes ); const ii = CONTEXT_IDS.length; for (let i = 0; i < ii; ++i) { try { const context = canvas.getContext(CONTEXT_IDS[i], attributes); if (context) { return ( /** @type {!WebGLRenderingContext} */ context ); } } catch { } } return null; } // node_modules/ol/webgl/Buffer.js var BufferUsage = { STATIC_DRAW, STREAM_DRAW, DYNAMIC_DRAW }; var WebGLArrayBuffer = class { /** * @param {number} type Buffer type, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER. * @param {number} [usage] Intended usage, either `STATIC_DRAW`, `STREAM_DRAW` or `DYNAMIC_DRAW`. * Default is `STATIC_DRAW`. */ constructor(type, usage) { this.array_ = null; this.type_ = type; assert( type === ARRAY_BUFFER || type === ELEMENT_ARRAY_BUFFER, "A `WebGLArrayBuffer` must either be of type `ELEMENT_ARRAY_BUFFER` or `ARRAY_BUFFER`" ); this.usage_ = usage !== void 0 ? usage : BufferUsage.STATIC_DRAW; } /** * Populates the buffer with an array of the given size (all values will be zeroes). * @param {number} size Array size * @return {WebGLArrayBuffer} This */ ofSize(size) { this.array_ = new (getArrayClassForType(this.type_))(size); return this; } /** * Populates the buffer with an array of the given size. * @param {Array} array Numerical array * @return {WebGLArrayBuffer} This */ fromArray(array) { this.array_ = getArrayClassForType(this.type_).from(array); return this; } /** * Populates the buffer with a raw binary array buffer. * @param {ArrayBuffer} buffer Raw binary buffer to populate the array with. Note that this buffer must have been * initialized for the same typed array class. * @return {WebGLArrayBuffer} This */ fromArrayBuffer(buffer) { this.array_ = new (getArrayClassForType(this.type_))(buffer); return this; } /** * @return {number} Buffer type. */ getType() { return this.type_; } /** * Will return null if the buffer was not initialized * @return {Float32Array|Uint32Array|null} Array. */ getArray() { return this.array_; } /** * @param {Float32Array|Uint32Array} array Array. */ setArray(array) { const ArrayType = getArrayClassForType(this.type_); if (!(array instanceof ArrayType)) { throw new Error(`Expected ${ArrayType}`); } this.array_ = array; } /** * @return {number} Usage. */ getUsage() { return this.usage_; } /** * Will return 0 if the buffer is not initialized * @return {number} Array size */ getSize() { return this.array_ ? this.array_.length : 0; } }; function getArrayClassForType(type) { switch (type) { case ARRAY_BUFFER: return Float32Array; case ELEMENT_ARRAY_BUFFER: return Uint32Array; default: return Float32Array; } } var Buffer_default = WebGLArrayBuffer; // node_modules/ol/webgl/ContextEventType.js var ContextEventType_default = { LOST: "webglcontextlost", RESTORED: "webglcontextrestored" }; // node_modules/ol/webgl/PostProcessingPass.js var DEFAULT_VERTEX_SHADER = ` precision mediump float; attribute vec2 a_position; varying vec2 v_texCoord; varying vec2 v_screenCoord; uniform vec2 u_screenSize; void main() { v_texCoord = a_position * 0.5 + 0.5; v_screenCoord = v_texCoord * u_screenSize; gl_Position = vec4(a_position, 0.0, 1.0); } `; var DEFAULT_FRAGMENT_SHADER = ` precision mediump float; uniform sampler2D u_image; uniform float u_opacity; varying vec2 v_texCoord; void main() { gl_FragColor = texture2D(u_image, v_texCoord) * u_opacity; } `; var WebGLPostProcessingPass = class { /** * @param {Options} options Options. */ constructor(options) { this.gl_ = options.webGlContext; const gl = this.gl_; this.scaleRatio_ = options.scaleRatio || 1; this.renderTargetTexture_ = gl.createTexture(); this.renderTargetTextureSize_ = null; this.frameBuffer_ = gl.createFramebuffer(); this.depthBuffer_ = gl.createRenderbuffer(); const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource( vertexShader, options.vertexShader || DEFAULT_VERTEX_SHADER ); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource( fragmentShader, options.fragmentShader || DEFAULT_FRAGMENT_SHADER ); gl.compileShader(fragmentShader); this.renderTargetProgram_ = gl.createProgram(); gl.attachShader(this.renderTargetProgram_, vertexShader); gl.attachShader(this.renderTargetProgram_, fragmentShader); gl.linkProgram(this.renderTargetProgram_); this.renderTargetVerticesBuffer_ = gl.createBuffer(); const verticesArray = [-1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1]; gl.bindBuffer(gl.ARRAY_BUFFER, this.renderTargetVerticesBuffer_); gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(verticesArray), gl.STATIC_DRAW ); this.renderTargetAttribLocation_ = gl.getAttribLocation( this.renderTargetProgram_, "a_position" ); this.renderTargetUniformLocation_ = gl.getUniformLocation( this.renderTargetProgram_, "u_screenSize" ); this.renderTargetOpacityLocation_ = gl.getUniformLocation( this.renderTargetProgram_, "u_opacity" ); this.renderTargetTextureLocation_ = gl.getUniformLocation( this.renderTargetProgram_, "u_image" ); this.uniforms_ = []; options.uniforms && Object.keys(options.uniforms).forEach((name) => { this.uniforms_.push({ value: options.uniforms[name], location: gl.getUniformLocation(this.renderTargetProgram_, name) }); }); } getRenderTargetTexture() { return this.renderTargetTexture_; } /** * Get the WebGL rendering context * @return {WebGLRenderingContext} The rendering context. */ getGL() { return this.gl_; } /** * Initialize the render target texture of the post process, make sure it is at the * right size and bind it as a render target for the next draw calls. * The last step to be initialized will be the one where the primitives are rendered. * @param {import("../Map.js").FrameState} frameState current frame state */ init(frameState) { const gl = this.getGL(); const textureSize = [ gl.drawingBufferWidth * this.scaleRatio_, gl.drawingBufferHeight * this.scaleRatio_ ]; gl.bindFramebuffer(gl.FRAMEBUFFER, this.getFrameBuffer()); gl.bindRenderbuffer(gl.RENDERBUFFER, this.getDepthBuffer()); gl.viewport(0, 0, textureSize[0], textureSize[1]); if (!this.renderTargetTextureSize_ || this.renderTargetTextureSize_[0] !== textureSize[0] || this.renderTargetTextureSize_[1] !== textureSize[1]) { this.renderTargetTextureSize_ = textureSize; const level = 0; const internalFormat = gl.RGBA; const border = 0; const format = gl.RGBA; const type = gl.UNSIGNED_BYTE; const data = null; gl.bindTexture(gl.TEXTURE_2D, this.renderTargetTexture_); gl.texImage2D( gl.TEXTURE_2D, level, internalFormat, textureSize[0], textureSize[1], border, format, type, data ); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.renderTargetTexture_, 0 ); gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, textureSize[0], textureSize[1] ); gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.depthBuffer_ ); } } /** * Render to the next postprocessing pass (or to the canvas if final pass). * @param {import("../Map.js").FrameState} frameState current frame state * @param {WebGLPostProcessingPass} [nextPass] Next pass, optional * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing. * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing. */ apply(frameState, nextPass, preCompose, postCompose) { const gl = this.getGL(); const size = frameState.size; gl.bindFramebuffer( gl.FRAMEBUFFER, nextPass ? nextPass.getFrameBuffer() : null ); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, this.renderTargetTexture_); if (!nextPass) { const canvasId = getUid(gl.canvas); if (!frameState.renderTargets[canvasId]) { const attributes = gl.getContextAttributes(); if (attributes && attributes.preserveDrawingBuffer) { gl.clearColor(0, 0, 0, 0); gl.clearDepth(1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); } frameState.renderTargets[canvasId] = true; } } gl.disable(gl.DEPTH_TEST); gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.bindBuffer(gl.ARRAY_BUFFER, this.renderTargetVerticesBuffer_); gl.useProgram(this.renderTargetProgram_); gl.enableVertexAttribArray(this.renderTargetAttribLocation_); gl.vertexAttribPointer( this.renderTargetAttribLocation_, 2, gl.FLOAT, false, 0, 0 ); gl.uniform2f(this.renderTargetUniformLocation_, size[0], size[1]); gl.uniform1i(this.renderTargetTextureLocation_, 0); const opacity = frameState.layerStatesArray[frameState.layerIndex].opacity; gl.uniform1f(this.renderTargetOpacityLocation_, opacity); this.applyUniforms(frameState); if (preCompose) { preCompose(gl, frameState); } gl.drawArrays(gl.TRIANGLES, 0, 6); if (postCompose) { postCompose(gl, frameState); } } /** * @return {WebGLFramebuffer} Frame buffer */ getFrameBuffer() { return this.frameBuffer_; } /** * @return {WebGLRenderbuffer} Depth buffer */ getDepthBuffer() { return this.depthBuffer_; } /** * Sets the custom uniforms based on what was given in the constructor. * @param {import("../Map.js").FrameState} frameState Frame state. * @private */ applyUniforms(frameState) { const gl = this.getGL(); let value; let textureSlot = 1; this.uniforms_.forEach(function(uniform) { value = typeof uniform.value === "function" ? uniform.value(frameState) : uniform.value; if (value instanceof HTMLCanvasElement || value instanceof ImageData) { if (!uniform.texture) { uniform.texture = gl.createTexture(); } gl.activeTexture(gl[`TEXTURE${textureSlot}`]); gl.bindTexture(gl.TEXTURE_2D, uniform.texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); if (value instanceof ImageData) { gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, value.width, value.height, 0, gl.UNSIGNED_BYTE, new Uint8Array(value.data) ); } else { gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, value ); } gl.uniform1i(uniform.location, textureSlot++); } else if (Array.isArray(value)) { switch (value.length) { case 2: gl.uniform2f(uniform.location, value[0], value[1]); return; case 3: gl.uniform3f(uniform.location, value[0], value[1], value[2]); return; case 4: gl.uniform4f( uniform.location, value[0], value[1], value[2], value[3] ); return; default: return; } } else if (typeof value === "number") { gl.uniform1f(uniform.location, value); } }); } }; var PostProcessingPass_default = WebGLPostProcessingPass; // node_modules/ol/webgl/Helper.js var DefaultUniform = { PROJECTION_MATRIX: "u_projectionMatrix", SCREEN_TO_WORLD_MATRIX: "u_screenToWorldMatrix", TIME: "u_time", ZOOM: "u_zoom", RESOLUTION: "u_resolution", ROTATION: "u_rotation", VIEWPORT_SIZE_PX: "u_viewportSizePx", PIXEL_RATIO: "u_pixelRatio", HIT_DETECTION: "u_hitDetection" }; var AttributeType = { UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT, FLOAT }; var canvasCache = {}; function getSharedCanvasCacheKey(key) { return "shared/" + key; } var uniqueCanvasCacheKeyCount = 0; function getUniqueCanvasCacheKey() { const key = "unique/" + uniqueCanvasCacheKeyCount; uniqueCanvasCacheKeyCount += 1; return key; } function getOrCreateContext(key) { let cacheItem = canvasCache[key]; if (!cacheItem) { const canvas = document.createElement("canvas"); canvas.width = 1; canvas.height = 1; canvas.style.position = "absolute"; canvas.style.left = "0"; const context = getContext(canvas); cacheItem = { users: 0, context }; canvasCache[key] = cacheItem; } cacheItem.users += 1; return cacheItem.context; } function releaseCanvas(key) { const cacheItem = canvasCache[key]; if (!cacheItem) { return; } cacheItem.users -= 1; if (cacheItem.users > 0) { return; } const gl = cacheItem.context; const extension = gl.getExtension("WEBGL_lose_context"); if (extension) { extension.loseContext(); } const canvas = gl.canvas; canvas.width = 1; canvas.height = 1; delete canvasCache[key]; } var WebGLHelper = class extends Disposable_default { /** * @param {Options} [options] Options. */ constructor(options) { super(); options = options || {}; this.boundHandleWebGLContextLost_ = this.handleWebGLContextLost.bind(this); this.boundHandleWebGLContextRestored_ = this.handleWebGLContextRestored.bind(this); this.canvasCacheKey_ = options.canvasCacheKey ? getSharedCanvasCacheKey(options.canvasCacheKey) : getUniqueCanvasCacheKey(); this.gl_ = getOrCreateContext(this.canvasCacheKey_); this.bufferCache_ = {}; this.extensionCache_ = {}; this.currentProgram_ = null; this.needsToBeRecreated_ = false; const canvas = this.gl_.canvas; canvas.addEventListener( ContextEventType_default.LOST, this.boundHandleWebGLContextLost_ ); canvas.addEventListener( ContextEventType_default.RESTORED, this.boundHandleWebGLContextRestored_ ); this.offsetRotateMatrix_ = create(); this.offsetScaleMatrix_ = create(); this.tmpMat4_ = create2(); this.uniformLocationsByProgram_ = {}; this.attribLocationsByProgram_ = {}; this.uniforms_ = []; if (options.uniforms) { this.setUniforms(options.uniforms); } this.postProcessPasses_ = options.postProcesses ? options.postProcesses.map( (options2) => new PostProcessingPass_default({ webGlContext: this.gl_, scaleRatio: options2.scaleRatio, vertexShader: options2.vertexShader, fragmentShader: options2.fragmentShader, uniforms: options2.uniforms }) ) : [new PostProcessingPass_default({ webGlContext: this.gl_ })]; this.shaderCompileErrors_ = null; this.startTime_ = Date.now(); this.maxAttributeCount_ = this.gl_.getParameter( this.gl_.MAX_VERTEX_ATTRIBS ); } /** * @param {Object} uniforms Uniform definitions. */ setUniforms(uniforms) { this.uniforms_ = []; this.addUniforms(uniforms); } /** * @param {Object} uniforms Uniform definitions. */ addUniforms(uniforms) { for (const name in uniforms) { this.uniforms_.push({ name, value: uniforms[name] }); } } /** * @param {string} canvasCacheKey The canvas cache key. * @return {boolean} The provided key matches the one this helper was constructed with. */ canvasCacheKeyMatches(canvasCacheKey) { return this.canvasCacheKey_ === getSharedCanvasCacheKey(canvasCacheKey); } /** * Get a WebGL extension. If the extension is not supported, null is returned. * Extensions are cached after they are enabled for the first time. * @param {string} name The extension name. * @return {Object|null} The extension or null if not supported. */ getExtension(name) { if (name in this.extensionCache_) { return this.extensionCache_[name]; } const extension = this.gl_.getExtension(name); this.extensionCache_[name] = extension; return extension; } /** * Just bind the buffer if it's in the cache. Otherwise create * the WebGL buffer, bind it, populate it, and add an entry to * the cache. * @param {import("./Buffer").default} buffer Buffer. */ bindBuffer(buffer) { const gl = this.gl_; const bufferKey = getUid(buffer); let bufferCache = this.bufferCache_[bufferKey]; if (!bufferCache) { const webGlBuffer = gl.createBuffer(); bufferCache = { buffer, webGlBuffer }; this.bufferCache_[bufferKey] = bufferCache; } gl.bindBuffer(buffer.getType(), bufferCache.webGlBuffer); } /** * Update the data contained in the buffer array; this is required for the * new data to be rendered * @param {import("./Buffer").default} buffer Buffer. */ flushBufferData(buffer) { const gl = this.gl_; this.bindBuffer(buffer); gl.bufferData(buffer.getType(), buffer.getArray(), buffer.getUsage()); } /** * @param {import("./Buffer.js").default} buf Buffer. */ deleteBuffer(buf) { const bufferKey = getUid(buf); delete this.bufferCache_[bufferKey]; } /** * Clean up. * @override */ disposeInternal() { const canvas = this.gl_.canvas; canvas.removeEventListener( ContextEventType_default.LOST, this.boundHandleWebGLContextLost_ ); canvas.removeEventListener( ContextEventType_default.RESTORED, this.boundHandleWebGLContextRestored_ ); releaseCanvas(this.canvasCacheKey_); delete this.gl_; } /** * Clear the buffer & set the viewport to draw. * Post process passes will be initialized here, the first one being bound as a render target for * subsequent draw calls. * @param {import("../Map.js").FrameState} frameState current frame state * @param {boolean} [disableAlphaBlend] If true, no alpha blending will happen. * @param {boolean} [enableDepth] If true, enables depth testing. */ prepareDraw(frameState, disableAlphaBlend, enableDepth) { const gl = this.gl_; const canvas = this.getCanvas(); const size = frameState.size; const pixelRatio = frameState.pixelRatio; if (canvas.width !== size[0] * pixelRatio || canvas.height !== size[1] * pixelRatio) { canvas.width = size[0] * pixelRatio; canvas.height = size[1] * pixelRatio; canvas.style.width = size[0] + "px"; canvas.style.height = size[1] + "px"; } for (let i = this.postProcessPasses_.length - 1; i >= 0; i--) { this.postProcessPasses_[i].init(frameState); } gl.bindTexture(gl.TEXTURE_2D, null); gl.clearColor(0, 0, 0, 0); gl.depthRange(0, 1); gl.clearDepth(1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, disableAlphaBlend ? gl.ZERO : gl.ONE_MINUS_SRC_ALPHA); if (enableDepth) { gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); } else { gl.disable(gl.DEPTH_TEST); } } /** * @param {WebGLFramebuffer|null} frameBuffer The frame buffer. * @param {WebGLTexture} [texture] The texture. */ bindFrameBuffer(frameBuffer, texture) { const gl = this.getGL(); gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); if (texture) { gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0 ); } } /** * Bind the frame buffer from the initial render. */ bindInitialFrameBuffer() { const gl = this.getGL(); const frameBuffer = this.postProcessPasses_[0].getFrameBuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); const texture = this.postProcessPasses_[0].getRenderTargetTexture(); gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0 ); } /** * Prepare a program to use a texture. * @param {WebGLTexture} texture The texture. * @param {number} slot The texture slot. * @param {string} uniformName The corresponding uniform name. */ bindTexture(texture, slot, uniformName) { const gl = this.gl_; gl.activeTexture(gl.TEXTURE0 + slot); gl.bindTexture(gl.TEXTURE_2D, texture); gl.uniform1i(this.getUniformLocation(uniformName), slot); } /** * Set up an attribute array buffer for use in the vertex shader. * @param {import("./Buffer").default} buffer The buffer. * @param {string} attributeName The attribute name. * @param {number} size The number of components per attribute vertex. */ bindAttribute(buffer, attributeName, size) { const gl = this.getGL(); this.bindBuffer(buffer); const index = this.getAttributeLocation(attributeName); gl.enableVertexAttribArray(index); gl.vertexAttribPointer(index, size, gl.FLOAT, false, 0, 0); } /** * Clear the render target & bind it for future draw operations. * This is similar to `prepareDraw`, only post processes will not be applied. * Note: the whole viewport will be drawn to the render target, regardless of its size. * @param {import("../Map.js").FrameState} frameState current frame state * @param {import("./RenderTarget.js").default} renderTarget Render target to draw to * @param {boolean} [disableAlphaBlend] If true, no alpha blending will happen. * @param {boolean} [enableDepth] If true, enables depth testing. */ prepareDrawToRenderTarget(frameState, renderTarget, disableAlphaBlend, enableDepth) { const gl = this.gl_; const size = renderTarget.getSize(); gl.bindFramebuffer(gl.FRAMEBUFFER, renderTarget.getFramebuffer()); gl.bindRenderbuffer(gl.RENDERBUFFER, renderTarget.getDepthbuffer()); gl.viewport(0, 0, size[0], size[1]); gl.bindTexture(gl.TEXTURE_2D, renderTarget.getTexture()); gl.clearColor(0, 0, 0, 0); gl.depthRange(0, 1); gl.clearDepth(1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, disableAlphaBlend ? gl.ZERO : gl.ONE_MINUS_SRC_ALPHA); if (enableDepth) { gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); } else { gl.disable(gl.DEPTH_TEST); } } /** * Execute a draw call based on the currently bound program, texture, buffers, attributes. * @param {number} start Start index. * @param {number} end End index. */ drawElements(start, end) { const gl = this.gl_; this.getExtension("OES_element_index_uint"); const elementType = gl.UNSIGNED_INT; const elementSize = 4; const numItems = end - start; const offsetInBytes = start * elementSize; gl.drawElements(gl.TRIANGLES, numItems, elementType, offsetInBytes); } /** * Apply the successive post process passes which will eventually render to the actual canvas. * @param {import("../Map.js").FrameState} frameState current frame state * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing. * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing. */ finalizeDraw(frameState, preCompose, postCompose) { for (let i = 0, ii = this.postProcessPasses_.length; i < ii; i++) { if (i === ii - 1) { this.postProcessPasses_[i].apply( frameState, null, preCompose, postCompose ); } else { this.postProcessPasses_[i].apply( frameState, this.postProcessPasses_[i + 1] ); } } } /** * @return {HTMLCanvasElement} Canvas. */ getCanvas() { return ( /** @type {HTMLCanvasElement} */ this.gl_.canvas ); } /** * Get the WebGL rendering context * @return {WebGLRenderingContext} The rendering context. */ getGL() { return this.gl_; } /** * Sets the default matrix uniforms for a given frame state. This is called internally in `prepareDraw`. * @param {import("../Map.js").FrameState} frameState Frame state. */ applyFrameState(frameState) { const size = frameState.size; const rotation = frameState.viewState.rotation; const pixelRatio = frameState.pixelRatio; this.setUniformFloatValue( DefaultUniform.TIME, (Date.now() - this.startTime_) * 1e-3 ); this.setUniformFloatValue(DefaultUniform.ZOOM, frameState.viewState.zoom); this.setUniformFloatValue( DefaultUniform.RESOLUTION, frameState.viewState.resolution ); this.setUniformFloatValue(DefaultUniform.PIXEL_RATIO, pixelRatio); this.setUniformFloatVec2(DefaultUniform.VIEWPORT_SIZE_PX, [ size[0], size[1] ]); this.setUniformFloatValue(DefaultUniform.ROTATION, rotation); } /** * Sets the `u_hitDetection` uniform. * @param {boolean} enabled Whether to enable the hit detection code path */ applyHitDetectionUniform(enabled) { const loc = this.getUniformLocation(DefaultUniform.HIT_DETECTION); this.getGL().uniform1i(loc, enabled ? 1 : 0); if (enabled) { this.setUniformFloatValue(DefaultUniform.PIXEL_RATIO, 0.5); } } /** * Sets the custom uniforms based on what was given in the constructor. This is called internally in `prepareDraw`. * @param {import("../Map.js").FrameState} frameState Frame state. */ applyUniforms(frameState) { const gl = this.gl_; let value; let textureSlot = 0; this.uniforms_.forEach((uniform) => { value = typeof uniform.value === "function" ? uniform.value(frameState) : uniform.value; if (value instanceof HTMLCanvasElement || value instanceof HTMLImageElement || value instanceof ImageData || value instanceof WebGLTexture) { if (value instanceof WebGLTexture && !uniform.texture) { uniform.prevValue = void 0; uniform.texture = value; } else if (!uniform.texture) { uniform.prevValue = void 0; uniform.texture = gl.createTexture(); } this.bindTexture(uniform.texture, textureSlot, uniform.name); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); const imageReady = !(value instanceof HTMLImageElement) || /** @type {HTMLImageElement} */ value.complete; if (!(value instanceof WebGLTexture) && imageReady && uniform.prevValue !== value) { uniform.prevValue = value; gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, value ); } textureSlot++; } else if (Array.isArray(value) && value.length === 6) { this.setUniformMatrixValue( uniform.name, fromTransform(this.tmpMat4_, value) ); } else if (Array.isArray(value) && value.length <= 4) { switch (value.length) { case 2: gl.uniform2f( this.getUniformLocation(uniform.name), value[0], value[1] ); return; case 3: gl.uniform3f( this.getUniformLocation(uniform.name), value[0], value[1], value[2] ); return; case 4: gl.uniform4f( this.getUniformLocation(uniform.name), value[0], value[1], value[2], value[3] ); return; default: return; } } else if (typeof value === "number") { gl.uniform1f(this.getUniformLocation(uniform.name), value); } }); } /** * Set up a program for use. The program will be set as the current one. Then, the uniforms used * in the program will be set based on the current frame state and the helper configuration. * @param {WebGLProgram} program Program. * @param {import("../Map.js").FrameState} [frameState] Frame state. */ useProgram(program, frameState) { this.disableAllAttributes_(); const gl = this.gl_; gl.useProgram(program); this.currentProgram_ = program; if (frameState) { this.applyFrameState(frameState); this.applyUniforms(frameState); } } /** * Will attempt to compile a vertex or fragment shader based on source * On error, the shader will be returned but * `gl.getShaderParameter(shader, gl.COMPILE_STATUS)` will return `true` * Use `gl.getShaderInfoLog(shader)` to have details * @param {string} source Shader source * @param {ShaderType} type VERTEX_SHADER or FRAGMENT_SHADER * @return {WebGLShader} Shader object */ compileShader(source, type) { const gl = this.gl_; const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); return shader; } /** * Create a program for a vertex and fragment shader. Throws if shader compilation fails. * @param {string} fragmentShaderSource Fragment shader source. * @param {string} vertexShaderSource Vertex shader source. * @return {WebGLProgram} Program */ getProgram(fragmentShaderSource, vertexShaderSource) { const gl = this.gl_; const fragmentShader = this.compileShader( fragmentShaderSource, gl.FRAGMENT_SHADER ); const vertexShader = this.compileShader( vertexShaderSource, gl.VERTEX_SHADER ); const program = gl.createProgram(); gl.attachShader(program, fragmentShader); gl.attachShader(program, vertexShader); gl.linkProgram(program); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { const message = `Fragment shader compilation failed: ${gl.getShaderInfoLog( fragmentShader )}`; throw new Error(message); } gl.deleteShader(fragmentShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { const message = `Vertex shader compilation failed: ${gl.getShaderInfoLog( vertexShader )}`; throw new Error(message); } gl.deleteShader(vertexShader); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { const message = `GL program linking failed: ${gl.getProgramInfoLog( program )}`; throw new Error(message); } return program; } /** * Will get the location from the shader or the cache * @param {string} name Uniform name * @return {WebGLUniformLocation} uniformLocation */ getUniformLocation(name) { const programUid = getUid(this.currentProgram_); if (this.uniformLocationsByProgram_[programUid] === void 0) { this.uniformLocationsByProgram_[programUid] = {}; } if (this.uniformLocationsByProgram_[programUid][name] === void 0) { this.uniformLocationsByProgram_[programUid][name] = this.gl_.getUniformLocation(this.currentProgram_, name); } return this.uniformLocationsByProgram_[programUid][name]; } /** * Will get the location from the shader or the cache * @param {string} name Attribute name * @return {number} attribLocation */ getAttributeLocation(name) { const programUid = getUid(this.currentProgram_); if (this.attribLocationsByProgram_[programUid] === void 0) { this.attribLocationsByProgram_[programUid] = {}; } if (this.attribLocationsByProgram_[programUid][name] === void 0) { this.attribLocationsByProgram_[programUid][name] = this.gl_.getAttribLocation(this.currentProgram_, name); } return this.attribLocationsByProgram_[programUid][name]; } /** * Sets the given transform to apply the rotation/translation/scaling of the given frame state. * The resulting transform can be used to convert world space coordinates to view coordinates in the [-1, 1] range. * @param {import("../Map.js").FrameState} frameState Frame state. * @param {import("../transform").Transform} transform Transform to update. * @return {import("../transform").Transform} The updated transform object. */ makeProjectionTransform(frameState, transform) { const size = frameState.size; const rotation = frameState.viewState.rotation; const resolution = frameState.viewState.resolution; const center = frameState.viewState.center; compose( transform, 0, 0, 2 / (resolution * size[0]), 2 / (resolution * size[1]), -rotation, -center[0], -center[1] ); return transform; } /** * Give a value for a standard float uniform * @param {string} uniform Uniform name * @param {number} value Value */ setUniformFloatValue(uniform, value) { this.gl_.uniform1f(this.getUniformLocation(uniform), value); } /** * Give a value for a vec2 uniform * @param {string} uniform Uniform name * @param {Array} value Array of length 4. */ setUniformFloatVec2(uniform, value) { this.gl_.uniform2fv(this.getUniformLocation(uniform), value); } /** * Give a value for a vec4 uniform * @param {string} uniform Uniform name * @param {Array} value Array of length 4. */ setUniformFloatVec4(uniform, value) { this.gl_.uniform4fv(this.getUniformLocation(uniform), value); } /** * Give a value for a standard matrix4 uniform * @param {string} uniform Uniform name * @param {Array} value Matrix value */ setUniformMatrixValue(uniform, value) { this.gl_.uniformMatrix4fv(this.getUniformLocation(uniform), false, value); } /** * Disable all vertex attributes. * @private */ disableAllAttributes_() { for (let i = 0; i < this.maxAttributeCount_; i++) { this.gl_.disableVertexAttribArray(i); } } /** * Will set the currently bound buffer to an attribute of the shader program. Used by `#enableAttributes` * internally. * @param {string} attribName Attribute name * @param {number} size Number of components per attributes * @param {number} type UNSIGNED_INT, UNSIGNED_BYTE, UNSIGNED_SHORT or FLOAT * @param {number} stride Stride in bytes (0 means attribs are packed) * @param {number} offset Offset in bytes * @private */ enableAttributeArray_(attribName, size, type, stride, offset) { const location = this.getAttributeLocation(attribName); if (location < 0) { return; } this.gl_.enableVertexAttribArray(location); this.gl_.vertexAttribPointer(location, size, type, false, stride, offset); } /** * Will enable the following attributes to be read from the currently bound buffer, * i.e. tell the GPU where to read the different attributes in the buffer. An error in the * size/type/order of attributes will most likely break the rendering and throw a WebGL exception. * @param {Array} attributes Ordered list of attributes to read from the buffer */ enableAttributes(attributes) { const stride = computeAttributesStride(attributes); let offset = 0; for (let i = 0; i < attributes.length; i++) { const attr = attributes[i]; this.enableAttributeArray_( attr.name, attr.size, attr.type || FLOAT, stride, offset ); offset += attr.size * getByteSizeFromType(attr.type); } } /** * WebGL context was lost * @param {WebGLContextEvent} event The context loss event. * @private */ handleWebGLContextLost(event) { clear(this.bufferCache_); this.currentProgram_ = null; event.preventDefault(); } /** * WebGL context was restored * @private */ handleWebGLContextRestored() { this.needsToBeRecreated_ = true; } /** * Returns whether this helper needs to be recreated, as the context was lost and then restored. * @return {boolean} Whether this helper needs to be recreated. */ needsToBeRecreated() { return this.needsToBeRecreated_; } /** * Will create or reuse a given webgl texture and apply the given size. If no image data * specified, the texture will be empty, otherwise image data will be used and the `size` * parameter will be ignored. If a Uint8Array is provided for data, a size must also be provided. * Note: wrap parameters are set to clamp to edge, min filter is set to linear. * @param {Array} size Expected size of the texture * @param {ImageData|HTMLImageElement|HTMLCanvasElement|Uint8Array|null} data Image data/object to bind to the texture * @param {WebGLTexture} [texture] Existing texture to reuse * @param {boolean} [nearest] Use gl.NEAREST for min/mag filter. * @return {WebGLTexture} The generated texture */ createTexture(size, data, texture, nearest) { const gl = this.gl_; texture = texture || gl.createTexture(); const filter = nearest ? gl.NEAREST : gl.LINEAR; gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); const level = 0; const internalFormat = gl.RGBA; const border = 0; const format = gl.RGBA; const type = gl.UNSIGNED_BYTE; if (data instanceof Uint8Array) { gl.texImage2D( gl.TEXTURE_2D, level, internalFormat, size[0], size[1], border, format, type, data ); } else if (data) { gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, format, type, data); } else { gl.texImage2D( gl.TEXTURE_2D, level, internalFormat, size[0], size[1], border, format, type, null ); } return texture; } }; function computeAttributesStride(attributes) { let stride = 0; for (let i = 0; i < attributes.length; i++) { const attr = attributes[i]; stride += attr.size * getByteSizeFromType(attr.type); } return stride; } function getByteSizeFromType(type) { switch (type) { case AttributeType.UNSIGNED_BYTE: return Uint8Array.BYTES_PER_ELEMENT; case AttributeType.UNSIGNED_SHORT: return Uint16Array.BYTES_PER_ELEMENT; case AttributeType.UNSIGNED_INT: return Uint32Array.BYTES_PER_ELEMENT; case AttributeType.FLOAT: default: return Float32Array.BYTES_PER_ELEMENT; } } var Helper_default = WebGLHelper; // node_modules/ol/webgl/BaseTileRepresentation.js var BaseTileRepresentation = class extends Target_default { /** * @param {TileRepresentationOptions} options The tile representation options. */ constructor(options) { super(); this.tile; this.handleTileChange_ = this.handleTileChange_.bind(this); this.gutter = options.gutter || 0; this.helper = options.helper; this.loaded = false; this.ready = false; } /** * @param {TileType} tile Tile. */ setTile(tile) { if (tile !== this.tile) { if (this.tile) { this.tile.removeEventListener(EventType_default.CHANGE, this.handleTileChange_); } this.tile = tile; this.loaded = tile.getState() === TileState_default.LOADED; if (this.loaded) { this.uploadTile(); } else { if (tile instanceof ImageTile_default) { const image = tile.getImage(); if (image instanceof Image && !image.crossOrigin) { image.crossOrigin = "anonymous"; } } tile.addEventListener(EventType_default.CHANGE, this.handleTileChange_); } } } /** * @abstract * @protected */ uploadTile() { abstract(); } setReady() { this.ready = true; this.dispatchEvent(EventType_default.CHANGE); } handleTileChange_() { if (this.tile.getState() === TileState_default.LOADED) { this.loaded = true; this.uploadTile(); } } /** * @param {import("./Helper.js").default} helper The WebGL helper. */ setHelper(helper) { this.helper = helper; if (this.helper && this.loaded) { this.uploadTile(); } } /** * @override */ disposeInternal() { this.setHelper(null); this.tile.removeEventListener(EventType_default.CHANGE, this.handleTileChange_); } }; var BaseTileRepresentation_default = BaseTileRepresentation; // node_modules/ol/webgl/TileTexture.js function bindAndConfigure(gl, texture, interpolate) { const resampleFilter = interpolate ? gl.LINEAR : gl.NEAREST; gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, resampleFilter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, resampleFilter); } function uploadImageTexture(gl, texture, image, interpolate) { bindAndConfigure(gl, texture, interpolate); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); } function uploadDataTexture(helper, texture, data, size, bandCount, interpolate) { const gl = helper.getGL(); let textureType; let canInterpolate; if (data instanceof Float32Array) { textureType = gl.FLOAT; helper.getExtension("OES_texture_float"); const extension = helper.getExtension("OES_texture_float_linear"); canInterpolate = extension !== null; } else { textureType = gl.UNSIGNED_BYTE; canInterpolate = true; } bindAndConfigure(gl, texture, interpolate && canInterpolate); const bytesPerRow = data.byteLength / size[1]; let unpackAlignment = 1; if (bytesPerRow % 8 === 0) { unpackAlignment = 8; } else if (bytesPerRow % 4 === 0) { unpackAlignment = 4; } else if (bytesPerRow % 2 === 0) { unpackAlignment = 2; } let format; switch (bandCount) { case 1: { format = gl.LUMINANCE; break; } case 2: { format = gl.LUMINANCE_ALPHA; break; } case 3: { format = gl.RGB; break; } case 4: { format = gl.RGBA; break; } default: { throw new Error(`Unsupported number of bands: ${bandCount}`); } } const oldUnpackAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT); gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment); gl.texImage2D( gl.TEXTURE_2D, 0, format, size[0], size[1], 0, format, textureType, data ); gl.pixelStorei(gl.UNPACK_ALIGNMENT, oldUnpackAlignment); } var pixelContext = null; function createPixelContext() { pixelContext = createCanvasContext2D(1, 1, void 0, { willReadFrequently: true }); } var TileTexture = class extends BaseTileRepresentation_default { /** * @param {import("./BaseTileRepresentation.js").TileRepresentationOptions} options The tile texture options. */ constructor(options) { super(options); this.textures = []; this.renderSize_ = toSize( options.grid.getTileSize(options.tile.tileCoord[0]) ); this.bandCount = NaN; const coords = new Buffer_default(ARRAY_BUFFER, STATIC_DRAW); coords.fromArray([ 0, // P0 1, 1, // P1 1, 1, // P2 0, 0, // P3 0 ]); this.helper.flushBufferData(coords); this.coords = coords; this.setTile(options.tile); } /** * @override * @param {import("./Helper.js").default} helper The WebGL helper. */ setHelper(helper) { var _a; const gl = (_a = this.helper) == null ? void 0 : _a.getGL(); if (gl) { this.helper.deleteBuffer(this.coords); for (let i = 0; i < this.textures.length; ++i) { gl.deleteTexture(this.textures[i]); } } super.setHelper(helper); if (helper) { helper.flushBufferData(this.coords); } } /** * @override */ uploadTile() { const helper = this.helper; const gl = helper.getGL(); const tile = this.tile; this.textures.length = 0; let data; if (tile instanceof ImageTile_default || tile instanceof Tile_default) { data = tile.getImage(); } else { data = tile.getData(); } const image = asImageLike(data); if (image) { const texture = gl.createTexture(); this.textures.push(texture); this.bandCount = 4; uploadImageTexture(gl, texture, image, tile.interpolate); this.setReady(); return; } data = asArrayLike(data); const sourceTileSize = ( /** @type {DataTile} */ tile.getSize() ); const pixelSize = [ sourceTileSize[0] + 2 * this.gutter, sourceTileSize[1] + 2 * this.gutter ]; const isFloat = data instanceof Float32Array; const pixelCount = pixelSize[0] * pixelSize[1]; const DataType = isFloat ? Float32Array : Uint8Array; const bytesPerElement = DataType.BYTES_PER_ELEMENT; const bytesPerRow = data.byteLength / pixelSize[1]; this.bandCount = Math.floor(bytesPerRow / bytesPerElement / pixelSize[0]); const textureCount = Math.ceil(this.bandCount / 4); if (textureCount === 1) { const texture = gl.createTexture(); this.textures.push(texture); uploadDataTexture( helper, texture, data, pixelSize, this.bandCount, tile.interpolate ); this.setReady(); return; } const textureDataArrays = new Array(textureCount); for (let textureIndex = 0; textureIndex < textureCount; ++textureIndex) { const texture = gl.createTexture(); this.textures.push(texture); const bandCount = textureIndex < textureCount - 1 ? 4 : (this.bandCount - 1) % 4 + 1; textureDataArrays[textureIndex] = new DataType(pixelCount * bandCount); } let dataIndex = 0; let rowOffset = 0; const colCount = pixelSize[0] * this.bandCount; for (let rowIndex = 0; rowIndex < pixelSize[1]; ++rowIndex) { for (let colIndex = 0; colIndex < colCount; ++colIndex) { const dataValue = data[rowOffset + colIndex]; const pixelIndex = Math.floor(dataIndex / this.bandCount); const bandIndex = colIndex % this.bandCount; const textureIndex = Math.floor(bandIndex / 4); const textureData = textureDataArrays[textureIndex]; const bandCount = textureData.length / pixelCount; const textureBandIndex = bandIndex % 4; textureData[pixelIndex * bandCount + textureBandIndex] = dataValue; ++dataIndex; } rowOffset += bytesPerRow / bytesPerElement; } for (let textureIndex = 0; textureIndex < textureCount; ++textureIndex) { const texture = this.textures[textureIndex]; const textureData = textureDataArrays[textureIndex]; const bandCount = textureData.length / pixelCount; uploadDataTexture( helper, texture, textureData, pixelSize, bandCount, tile.interpolate ); } this.setReady(); } /** * @param {import("../DataTile.js").ImageLike} image The image. * @param {number} renderCol The column index (in rendered tile space). * @param {number} renderRow The row index (in rendered tile space). * @return {Uint8ClampedArray|null} The data. * @private */ getImagePixelData_(image, renderCol, renderRow) { const gutter = this.gutter; const renderWidth = this.renderSize_[0]; const renderHeight = this.renderSize_[1]; if (!pixelContext) { createPixelContext(); } pixelContext.clearRect(0, 0, 1, 1); const sourceWidth = image.width; const sourceHeight = image.height; const sourceWidthWithoutGutter = sourceWidth - 2 * gutter; const sourceHeightWithoutGutter = sourceHeight - 2 * gutter; const sourceCol = gutter + Math.floor(sourceWidthWithoutGutter * (renderCol / renderWidth)); const sourceRow = gutter + Math.floor(sourceHeightWithoutGutter * (renderRow / renderHeight)); let data; try { pixelContext.drawImage(image, sourceCol, sourceRow, 1, 1, 0, 0, 1, 1); data = pixelContext.getImageData(0, 0, 1, 1).data; } catch { pixelContext = null; return null; } return data; } /** * @param {import("../DataTile.js").ArrayLike} data The data. * @param {import("../size.js").Size} sourceSize The size. * @param {number} renderCol The column index (in rendered tile space). * @param {number} renderRow The row index (in rendered tile space). * @return {import("../DataTile.js").ArrayLike|null} The data. * @private */ getArrayPixelData_(data, sourceSize, renderCol, renderRow) { const gutter = this.gutter; const renderWidth = this.renderSize_[0]; const renderHeight = this.renderSize_[1]; const sourceWidthWithoutGutter = sourceSize[0]; const sourceHeightWithoutGutter = sourceSize[1]; const sourceWidth = sourceWidthWithoutGutter + 2 * gutter; const sourceHeight = sourceHeightWithoutGutter + 2 * gutter; const sourceCol = gutter + Math.floor(sourceWidthWithoutGutter * (renderCol / renderWidth)); const sourceRow = gutter + Math.floor(sourceHeightWithoutGutter * (renderRow / renderHeight)); if (data instanceof DataView) { const bytesPerPixel = data.byteLength / (sourceWidth * sourceHeight); const offset2 = bytesPerPixel * (sourceRow * sourceWidth + sourceCol); const buffer = data.buffer.slice(offset2, offset2 + bytesPerPixel); return new DataView(buffer); } const offset = this.bandCount * (sourceRow * sourceWidth + sourceCol); return data.slice(offset, offset + this.bandCount); } /** * Get data for a pixel. If the tile is not loaded, null is returned. * @param {number} renderCol The column index (in rendered tile space). * @param {number} renderRow The row index (in rendered tile space). * @return {import("../DataTile.js").ArrayLike|null} The data. */ getPixelData(renderCol, renderRow) { if (!this.loaded) { return null; } if (this.tile instanceof DataTile_default) { const data = this.tile.getData(); const arrayData = asArrayLike(data); if (arrayData) { const sourceSize = this.tile.getSize(); return this.getArrayPixelData_( arrayData, sourceSize, renderCol, renderRow ); } return this.getImagePixelData_(asImageLike(data), renderCol, renderRow); } return this.getImagePixelData_(this.tile.getImage(), renderCol, renderRow); } }; var TileTexture_default = TileTexture; // node_modules/ol/renderer/webgl/Layer.js var WebGLLayerRenderer = class _WebGLLayerRenderer extends Layer_default { /** * @param {LayerType} layer Layer. * @param {Options} [options] Options. */ constructor(layer, options) { super(layer); options = options || {}; this.inversePixelTransform_ = create(); this.postProcesses_ = options.postProcesses; this.uniforms_ = options.uniforms; this.helper; this.onMapChanged_ = () => { this.clearCache(); this.removeHelper(); }; layer.addChangeListener(Property_default.MAP, this.onMapChanged_); this.dispatchPreComposeEvent = this.dispatchPreComposeEvent.bind(this); this.dispatchPostComposeEvent = this.dispatchPostComposeEvent.bind(this); } /** * @param {WebGLRenderingContext} context The WebGL rendering context. * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ dispatchPreComposeEvent(context, frameState) { const layer = this.getLayer(); if (layer.hasListener(EventType_default2.PRECOMPOSE)) { const event = new Event_default( EventType_default2.PRECOMPOSE, void 0, frameState, context ); layer.dispatchEvent(event); } } /** * @param {WebGLRenderingContext} context The WebGL rendering context. * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ dispatchPostComposeEvent(context, frameState) { const layer = this.getLayer(); if (layer.hasListener(EventType_default2.POSTCOMPOSE)) { const event = new Event_default( EventType_default2.POSTCOMPOSE, void 0, frameState, context ); layer.dispatchEvent(event); } } /** * Reset options (only handles uniforms). * @param {Options} options Options. */ reset(options) { this.uniforms_ = options.uniforms; if (this.helper) { this.helper.setUniforms(this.uniforms_); } } /** * @protected */ removeHelper() { if (this.helper) { this.helper.dispose(); delete this.helper; } } /** * Determine whether renderFrame should be called. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. * @override */ prepareFrame(frameState) { if (this.getLayer().getRenderSource()) { let incrementGroup = true; let groupNumber = -1; let className; for (let i = 0, ii = frameState.layerStatesArray.length; i < ii; i++) { const layer = frameState.layerStatesArray[i].layer; const renderer = layer.getRenderer(); if (!(renderer instanceof _WebGLLayerRenderer)) { incrementGroup = true; continue; } const layerClassName = layer.getClassName(); if (incrementGroup || layerClassName !== className) { groupNumber += 1; incrementGroup = false; } className = layerClassName; if (renderer === this) { break; } } const canvasCacheKey = "map/" + frameState.mapId + "/group/" + groupNumber; if (!this.helper || !this.helper.canvasCacheKeyMatches(canvasCacheKey) || this.helper.needsToBeRecreated()) { this.removeHelper(); this.helper = new Helper_default({ postProcesses: this.postProcesses_, uniforms: this.uniforms_, canvasCacheKey }); if (className) { this.helper.getCanvas().className = className; } this.afterHelperCreated(); } } return this.prepareFrameInternal(frameState); } /** * @protected */ afterHelperCreated() { } /** * Determine whether renderFrame should be called. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. * @protected */ prepareFrameInternal(frameState) { return true; } /** * @protected */ clearCache() { } /** * Clean up. * @override */ disposeInternal() { var _a; this.clearCache(); this.removeHelper(); (_a = this.getLayer()) == null ? void 0 : _a.removeChangeListener( Property_default.MAP, this.onMapChanged_ ); super.disposeInternal(); } /** * @param {import("../../render/EventType.js").default} type Event type. * @param {WebGLRenderingContext} context The rendering context. * @param {import("../../Map.js").FrameState} frameState Frame state. * @private */ dispatchRenderEvent_(type, context, frameState) { const layer = this.getLayer(); if (layer.hasListener(type)) { compose( this.inversePixelTransform_, 0, 0, frameState.pixelRatio, -frameState.pixelRatio, 0, 0, -frameState.size[1] ); const event = new Event_default( type, this.inversePixelTransform_, frameState, context ); layer.dispatchEvent(event); } } /** * @param {WebGLRenderingContext} context The rendering context. * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ preRender(context, frameState) { this.dispatchRenderEvent_(EventType_default2.PRERENDER, context, frameState); } /** * @param {WebGLRenderingContext} context The rendering context. * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ postRender(context, frameState) { this.dispatchRenderEvent_(EventType_default2.POSTRENDER, context, frameState); } }; var Layer_default2 = WebGLLayerRenderer; // node_modules/ol/renderer/webgl/TileLayerBase.js var Uniforms = { TILE_TRANSFORM: "u_tileTransform", TRANSITION_ALPHA: "u_transitionAlpha", DEPTH: "u_depth", RENDER_EXTENT: "u_renderExtent", // intersection of layer, source, and view extent PATTERN_ORIGIN: "u_patternOrigin", RESOLUTION: "u_resolution", ZOOM: "u_zoom", GLOBAL_ALPHA: "u_globalAlpha", PROJECTION_MATRIX: "u_projectionMatrix", SCREEN_TO_WORLD_MATRIX: "u_screenToWorldMatrix" }; function depthForZ(z) { return 1 / (z + 2); } function newTileRepresentationLookup() { return { tileIds: /* @__PURE__ */ new Set(), representationsByZ: {} }; } function lookupHasTile(tileRepresentationLookup, tile) { return tileRepresentationLookup.tileIds.has(getUid(tile)); } function addTileRepresentationToLookup(tileRepresentationLookup, tileRepresentation, z) { const representationsByZ = tileRepresentationLookup.representationsByZ; if (!(z in representationsByZ)) { representationsByZ[z] = /* @__PURE__ */ new Set(); } representationsByZ[z].add(tileRepresentation); tileRepresentationLookup.tileIds.add(getUid(tileRepresentation.tile)); } function getRenderExtent(frameState, extent) { const layerState = frameState.layerStatesArray[frameState.layerIndex]; if (layerState.extent) { extent = getIntersection( extent, fromUserExtent(layerState.extent, frameState.viewState.projection) ); } const source = ( /** @type {import("../../source/Tile.js").default} */ layerState.layer.getRenderSource() ); if (!source.getWrapX()) { const gridExtent = source.getTileGridForProjection(frameState.viewState.projection).getExtent(); if (gridExtent) { extent = getIntersection(extent, gridExtent); } } return extent; } function getCacheKey(source, tileCoord) { return `${getUid(source)},${source.getKey()},${source.getRevision()},${getKey(tileCoord)}`; } var WebGLBaseTileLayerRenderer = class extends Layer_default2 { /** * @param {LayerType} tileLayer Tile layer. * @param {Options} options Options. */ constructor(tileLayer, options) { super(tileLayer, { uniforms: options.uniforms, postProcesses: options.postProcesses }); this.renderComplete = false; this.tileTransform_ = create(); this.tempMat4 = create2(); this.tempTileRange_ = new TileRange_default(0, 0, 0, 0); this.tempTileCoord_ = createOrUpdate(0, 0, 0); this.tempSize_ = [0, 0]; const cacheSize = options.cacheSize !== void 0 ? options.cacheSize : 512; this.tileRepresentationCache = new LRUCache_default(cacheSize); this.frameState = null; this.renderedProjection_ = void 0; } /** * @param {Options} options Options. * @override */ reset(options) { super.reset({ uniforms: options.uniforms }); } /** * Determine whether renderFrame should be called. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} Layer is ready to be rendered. * @override */ prepareFrameInternal(frameState) { if (!this.renderedProjection_) { this.renderedProjection_ = frameState.viewState.projection; } else if (frameState.viewState.projection !== this.renderedProjection_) { this.clearCache(); this.renderedProjection_ = frameState.viewState.projection; } const layer = this.getLayer(); const source = layer.getRenderSource(); if (!source) { return false; } if (isEmpty(getRenderExtent(frameState, frameState.extent))) { return false; } return source.getState() === "ready"; } /** * @abstract * @param {import("../../webgl/BaseTileRepresentation.js").TileRepresentationOptions} options tile representation options * @return {TileRepresentation} A new tile representation * @protected */ createTileRepresentation(options) { return abstract(); } /** * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {import("../../extent.js").Extent} extent The extent to be rendered. * @param {number} initialZ The zoom level. * @param {TileRepresentationLookup} tileRepresentationLookup The zoom level. * @param {number} preload Number of additional levels to load. */ enqueueTiles(frameState, extent, initialZ, tileRepresentationLookup, preload) { const viewState = frameState.viewState; const tileLayer = this.getLayer(); const tileSource = tileLayer.getRenderSource(); const tileGrid = tileSource.getTileGridForProjection(viewState.projection); const gutter = tileSource.getGutterForProjection(viewState.projection); const tileSourceKey = getUid(tileSource); if (!(tileSourceKey in frameState.wantedTiles)) { frameState.wantedTiles[tileSourceKey] = {}; } const wantedTiles = frameState.wantedTiles[tileSourceKey]; const tileRepresentationCache = this.tileRepresentationCache; const map = tileLayer.getMapInternal(); const minZ = Math.max( initialZ - preload, tileGrid.getMinZoom(), tileGrid.getZForResolution( Math.min( tileLayer.getMaxResolution(), map ? map.getView().getResolutionForZoom(Math.max(tileLayer.getMinZoom(), 0)) : tileGrid.getResolution(0) ), tileSource.zDirection ) ); const rotation = viewState.rotation; const viewport = rotation ? getRotatedViewport( viewState.center, viewState.resolution, rotation, frameState.size ) : void 0; for (let z = initialZ; z >= minZ; --z) { const tileRange = tileGrid.getTileRangeForExtentAndZ( extent, z, this.tempTileRange_ ); const tileResolution = tileGrid.getResolution(z); for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let y = tileRange.minY; y <= tileRange.maxY; ++y) { if (rotation && !tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)) { continue; } const tileCoord = createOrUpdate(z, x, y, this.tempTileCoord_); const cacheKey = getCacheKey(tileSource, tileCoord); let tileRepresentation; let tile; if (tileRepresentationCache.containsKey(cacheKey)) { tileRepresentation = tileRepresentationCache.get(cacheKey); tile = tileRepresentation.tile; } if (!tileRepresentation || tileRepresentation.tile.key !== tileSource.getKey()) { tile = tileSource.getTile( z, x, y, frameState.pixelRatio, viewState.projection ); if (!tile) { continue; } } if (lookupHasTile(tileRepresentationLookup, tile)) { continue; } if (!tileRepresentation) { tileRepresentation = this.createTileRepresentation({ tile, grid: tileGrid, helper: this.helper, gutter }); tileRepresentationCache.set(cacheKey, tileRepresentation); } else { tileRepresentation.setTile(tile); } addTileRepresentationToLookup( tileRepresentationLookup, tileRepresentation, z ); const tileQueueKey = tile.getKey(); wantedTiles[tileQueueKey] = true; if (tile.getState() === TileState_default.IDLE) { if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) { frameState.tileQueue.enqueue([ tile, tileSourceKey, tileGrid.getTileCoordCenter(tileCoord), tileResolution ]); } } } } } } /** * @param {import("../../Map.js").FrameState} frameState Frame state. * @param {boolean} tilesWithAlpha True if at least one of the rendered tiles has alpha * @protected */ beforeTilesRender(frameState, tilesWithAlpha) { this.helper.prepareDraw(this.frameState, !tilesWithAlpha, true); } /** * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {boolean} If returns false, tile mask rendering will be skipped * @protected */ beforeTilesMaskRender(frameState) { return false; } /** * @param {TileRepresentation} tileRepresentation Tile representation * @param {import("../../transform.js").Transform} tileTransform Tile transform * @param {import("../../Map.js").FrameState} frameState Frame state * @param {import("../../extent.js").Extent} renderExtent Render extent * @param {number} tileResolution Tile resolution * @param {import("../../size.js").Size} tileSize Tile size * @param {import("../../coordinate.js").Coordinate} tileOrigin Tile origin * @param {import("../../extent.js").Extent} tileExtent tile Extent * @param {number} depth Depth * @param {number} gutter Gutter * @param {number} alpha Alpha * @protected */ renderTile(tileRepresentation, tileTransform, frameState, renderExtent, tileResolution, tileSize, tileOrigin, tileExtent, depth, gutter, alpha) { } /** * @param {TileRepresentation} tileRepresentation Tile representation * @param {number} tileZ Tile Z * @param {import("../../extent.js").Extent} extent Render extent * @param {number} depth Depth * @protected */ renderTileMask(tileRepresentation, tileZ, extent, depth) { } drawTile_(frameState, tileRepresentation, tileZ, gutter, extent, alphaLookup, tileGrid) { if (!tileRepresentation.ready) { return; } const tile = tileRepresentation.tile; const tileCoord = tile.tileCoord; const tileCoordKey = getKey(tileCoord); const alpha = tileCoordKey in alphaLookup ? alphaLookup[tileCoordKey] : 1; const tileResolution = tileGrid.getResolution(tileZ); const tileSize = toSize(tileGrid.getTileSize(tileZ), this.tempSize_); const tileOrigin = tileGrid.getOrigin(tileZ); const tileExtent = tileGrid.getTileCoordExtent(tileCoord); const depth = alpha < 1 ? -1 : depthForZ(tileZ); if (alpha < 1) { frameState.animate = true; } const viewState = frameState.viewState; const centerX = viewState.center[0]; const centerY = viewState.center[1]; const tileWidthWithGutter = tileSize[0] + 2 * gutter; const tileHeightWithGutter = tileSize[1] + 2 * gutter; const aspectRatio = tileWidthWithGutter / tileHeightWithGutter; const centerI = (centerX - tileOrigin[0]) / (tileSize[0] * tileResolution); const centerJ = (tileOrigin[1] - centerY) / (tileSize[1] * tileResolution); const tileScale = viewState.resolution / tileResolution; const tileCenterI = tileCoord[1]; const tileCenterJ = tileCoord[2]; reset(this.tileTransform_); scale( this.tileTransform_, 2 / (frameState.size[0] * tileScale / tileWidthWithGutter), -2 / (frameState.size[1] * tileScale / tileWidthWithGutter) ); rotate(this.tileTransform_, viewState.rotation); scale(this.tileTransform_, 1, 1 / aspectRatio); translate( this.tileTransform_, (tileSize[0] * (tileCenterI - centerI) - gutter) / tileWidthWithGutter, (tileSize[1] * (tileCenterJ - centerJ) - gutter) / tileHeightWithGutter ); this.renderTile( /** @type {TileRepresentation} */ tileRepresentation, this.tileTransform_, frameState, extent, tileResolution, tileSize, tileOrigin, tileExtent, depth, gutter, alpha ); } /** * Render the layer. * @param {import("../../Map.js").FrameState} frameState Frame state. * @return {HTMLElement} The rendered element. * @override */ renderFrame(frameState) { this.frameState = frameState; this.renderComplete = true; const gl = this.helper.getGL(); this.preRender(gl, frameState); const viewState = frameState.viewState; const tileLayer = this.getLayer(); const tileSource = tileLayer.getRenderSource(); const tileGrid = tileSource.getTileGridForProjection(viewState.projection); const gutter = tileSource.getGutterForProjection(viewState.projection); const extent = getRenderExtent(frameState, frameState.extent); const z = tileGrid.getZForResolution( viewState.resolution, tileSource.zDirection ); const tileRepresentationLookup = newTileRepresentationLookup(); const preload = tileLayer.getPreload(); if (frameState.nextExtent) { const targetZ = tileGrid.getZForResolution( viewState.nextResolution, tileSource.zDirection ); const nextExtent = getRenderExtent(frameState, frameState.nextExtent); this.enqueueTiles( frameState, nextExtent, targetZ, tileRepresentationLookup, preload ); } this.enqueueTiles(frameState, extent, z, tileRepresentationLookup, 0); if (preload > 0) { setTimeout(() => { this.enqueueTiles( frameState, extent, z - 1, tileRepresentationLookup, preload - 1 ); }, 0); } const alphaLookup = {}; let blend = false; const representationsByZ = tileRepresentationLookup.representationsByZ; if (z in representationsByZ) { const uid = getUid(this); const time = frameState.time; for (const tileRepresentation of representationsByZ[z]) { const tile = tileRepresentation.tile; if (tile.getState() === TileState_default.EMPTY) { continue; } const tileCoord = tile.tileCoord; if (tileRepresentation.ready) { const alpha = tile.getAlpha(uid, time); if (alpha === 1) { tile.endTransition(uid); continue; } blend = true; const tileCoordKey = getKey(tileCoord); alphaLookup[tileCoordKey] = alpha; } this.renderComplete = false; const coveredByChildren = this.findAltTiles_( tileGrid, tileCoord, z + 1, tileRepresentationLookup ); if (coveredByChildren) { continue; } const minZoom = tileGrid.getMinZoom(); for (let parentZ = z - 1; parentZ >= minZoom; --parentZ) { const coveredByParent = this.findAltTiles_( tileGrid, tileCoord, parentZ, tileRepresentationLookup ); if (coveredByParent) { break; } } } } const zs = Object.keys(representationsByZ).map(Number).sort(descending); const renderTileMask = this.beforeTilesMaskRender(frameState); if (renderTileMask) { for (let j = 0, jj = zs.length; j < jj; ++j) { const tileZ = zs[j]; for (const tileRepresentation of representationsByZ[tileZ]) { const tileCoord = tileRepresentation.tile.tileCoord; const tileCoordKey = getKey(tileCoord); if (tileCoordKey in alphaLookup) { continue; } const tileExtent = tileGrid.getTileCoordExtent(tileCoord); this.renderTileMask( /** @type {TileRepresentation} */ tileRepresentation, tileZ, tileExtent, depthForZ(tileZ) ); } } } this.beforeTilesRender(frameState, blend); for (let j = 0, jj = zs.length; j < jj; ++j) { const tileZ = zs[j]; for (const tileRepresentation of representationsByZ[tileZ]) { const tileCoord = tileRepresentation.tile.tileCoord; const tileCoordKey = getKey(tileCoord); if (tileCoordKey in alphaLookup) { continue; } this.drawTile_( frameState, tileRepresentation, tileZ, gutter, extent, alphaLookup, tileGrid ); } } if (z in representationsByZ) { for (const tileRepresentation of representationsByZ[z]) { const tileCoord = tileRepresentation.tile.tileCoord; const tileCoordKey = getKey(tileCoord); if (tileCoordKey in alphaLookup) { this.drawTile_( frameState, tileRepresentation, z, gutter, extent, alphaLookup, tileGrid ); } } } this.beforeFinalize(frameState); this.helper.finalizeDraw( frameState, this.dispatchPreComposeEvent, this.dispatchPostComposeEvent ); const canvas = this.helper.getCanvas(); const tileRepresentationCache = this.tileRepresentationCache; while (tileRepresentationCache.canExpireCache()) { const tileRepresentation = tileRepresentationCache.pop(); tileRepresentation.dispose(); } this.postRender(gl, frameState); return canvas; } /** * @param {import("../../Map.js").FrameState} frameState Frame state. * @protected */ beforeFinalize(frameState) { return; } /** * Look for tiles covering the provided tile coordinate at an alternate * zoom level. Loaded tiles will be added to the provided tile representation lookup. * @param {import("../../tilegrid/TileGrid.js").default} tileGrid The tile grid. * @param {import("../../tilecoord.js").TileCoord} tileCoord The target tile coordinate. * @param {number} altZ The alternate zoom level. * @param {TileRepresentationLookup} tileRepresentationLookup Lookup of * tile representations by zoom level. * @return {boolean} The tile coordinate is covered by loaded tiles at the alternate zoom level. * @private */ findAltTiles_(tileGrid, tileCoord, altZ, tileRepresentationLookup) { const tileRange = tileGrid.getTileRangeForTileCoordAndZ( tileCoord, altZ, this.tempTileRange_ ); if (!tileRange) { return false; } let covered = true; const tileRepresentationCache = this.tileRepresentationCache; const source = this.getLayer().getRenderSource(); for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let y = tileRange.minY; y <= tileRange.maxY; ++y) { const cacheKey = getCacheKey(source, [altZ, x, y]); let loaded = false; if (tileRepresentationCache.containsKey(cacheKey)) { const tileRepresentation = tileRepresentationCache.get(cacheKey); if (tileRepresentation.ready && !lookupHasTile(tileRepresentationLookup, tileRepresentation.tile)) { addTileRepresentationToLookup( tileRepresentationLookup, tileRepresentation, altZ ); loaded = true; } } if (!loaded) { covered = false; } } } return covered; } /** * @override */ clearCache() { super.clearCache(); const tileRepresentationCache = this.tileRepresentationCache; tileRepresentationCache.forEach( (tileRepresentation) => tileRepresentation.dispose() ); tileRepresentationCache.clear(); } /** * @override */ afterHelperCreated() { super.afterHelperCreated(); this.tileRepresentationCache.forEach( (tileRepresentation) => tileRepresentation.setHelper(this.helper) ); } /** * Clean up. * @override */ disposeInternal() { super.disposeInternal(); delete this.frameState; } }; var TileLayerBase_default = WebGLBaseTileLayerRenderer; // node_modules/ol/renderer/webgl/TileLayer.js var Uniforms2 = { ...Uniforms, TILE_TEXTURE_ARRAY: "u_tileTextures", TEXTURE_PIXEL_WIDTH: "u_texturePixelWidth", TEXTURE_PIXEL_HEIGHT: "u_texturePixelHeight", TEXTURE_RESOLUTION: "u_textureResolution", // map units per texture pixel TEXTURE_ORIGIN_X: "u_textureOriginX", // map x coordinate of left edge of texture TEXTURE_ORIGIN_Y: "u_textureOriginY" // map y coordinate of top edge of texture }; var Attributes = { TEXTURE_COORD: "a_textureCoord" }; var attributeDescriptions = [ { name: Attributes.TEXTURE_COORD, size: 2, type: AttributeType.FLOAT } ]; var WebGLTileLayerRenderer = class extends TileLayerBase_default { /** * @param {LayerType} tileLayer Tile layer. * @param {Options} options Options. */ constructor(tileLayer, options) { super(tileLayer, options); this.program_; this.vertexShader_ = options.vertexShader; this.fragmentShader_ = options.fragmentShader; this.indices_ = new Buffer_default(ELEMENT_ARRAY_BUFFER, STATIC_DRAW); this.indices_.fromArray([0, 1, 3, 1, 2, 3]); this.paletteTextures_ = options.paletteTextures || []; } /** * @param {Options} options Options. * @override */ reset(options) { super.reset(options); if (this.helper) { const gl = this.helper.getGL(); for (const paletteTexture of this.paletteTextures_) { paletteTexture.delete(gl); } } this.vertexShader_ = options.vertexShader; this.fragmentShader_ = options.fragmentShader; this.paletteTextures_ = options.paletteTextures || []; if (this.helper) { this.program_ = this.helper.getProgram( this.fragmentShader_, this.vertexShader_ ); const gl = this.helper.getGL(); for (const paletteTexture of this.paletteTextures_) { paletteTexture.getTexture(gl); } } } /** * @override */ afterHelperCreated() { super.afterHelperCreated(); const gl = this.helper.getGL(); for (const paletteTexture of this.paletteTextures_) { paletteTexture.getTexture(gl); } this.program_ = this.helper.getProgram( this.fragmentShader_, this.vertexShader_ ); this.helper.flushBufferData(this.indices_); } /** * @override */ removeHelper() { if (this.helper) { const gl = this.helper.getGL(); for (const paletteTexture of this.paletteTextures_) { paletteTexture.delete(gl); } } super.removeHelper(); } /** * @override */ createTileRepresentation(options) { return new TileTexture_default(options); } /** * @override */ beforeTilesRender(frameState, tilesWithAlpha) { super.beforeTilesRender(frameState, tilesWithAlpha); this.helper.useProgram(this.program_, frameState); } /** * @override */ renderTile(tileTexture, tileTransform, frameState, renderExtent, tileResolution, tileSize, tileOrigin, tileExtent, depth, gutter, alpha) { const gl = this.helper.getGL(); this.helper.bindBuffer(tileTexture.coords); this.helper.bindBuffer(this.indices_); this.helper.enableAttributes(attributeDescriptions); let textureSlot = 0; while (textureSlot < tileTexture.textures.length) { const uniformName = `${Uniforms2.TILE_TEXTURE_ARRAY}[${textureSlot}]`; this.helper.bindTexture( tileTexture.textures[textureSlot], textureSlot, uniformName ); ++textureSlot; } for (let paletteIndex = 0; paletteIndex < this.paletteTextures_.length; ++paletteIndex) { const paletteTexture = this.paletteTextures_[paletteIndex]; const texture = paletteTexture.getTexture(gl); this.helper.bindTexture(texture, textureSlot, paletteTexture.name); ++textureSlot; } const viewState = frameState.viewState; const tileWidthWithGutter = tileSize[0] + 2 * gutter; const tileHeightWithGutter = tileSize[1] + 2 * gutter; const tile = tileTexture.tile; const tileCoord = tile.tileCoord; const tileCenterI = tileCoord[1]; const tileCenterJ = tileCoord[2]; this.helper.setUniformMatrixValue( Uniforms2.TILE_TRANSFORM, fromTransform(this.tempMat4, tileTransform) ); this.helper.setUniformFloatValue(Uniforms2.TRANSITION_ALPHA, alpha); this.helper.setUniformFloatValue(Uniforms2.DEPTH, depth); let gutterExtent = renderExtent; if (gutter > 0) { gutterExtent = tileExtent; getIntersection(gutterExtent, renderExtent, gutterExtent); } this.helper.setUniformFloatVec4(Uniforms2.RENDER_EXTENT, gutterExtent); this.helper.setUniformFloatValue(Uniforms2.RESOLUTION, viewState.resolution); this.helper.setUniformFloatValue(Uniforms2.ZOOM, viewState.zoom); this.helper.setUniformFloatValue( Uniforms2.TEXTURE_PIXEL_WIDTH, tileWidthWithGutter ); this.helper.setUniformFloatValue( Uniforms2.TEXTURE_PIXEL_HEIGHT, tileHeightWithGutter ); this.helper.setUniformFloatValue( Uniforms2.TEXTURE_RESOLUTION, tileResolution ); this.helper.setUniformFloatValue( Uniforms2.TEXTURE_ORIGIN_X, tileOrigin[0] + tileCenterI * tileSize[0] * tileResolution - gutter * tileResolution ); this.helper.setUniformFloatValue( Uniforms2.TEXTURE_ORIGIN_Y, tileOrigin[1] - tileCenterJ * tileSize[1] * tileResolution + gutter * tileResolution ); this.helper.drawElements(0, this.indices_.getSize()); } /** * @param {import("../../pixel.js").Pixel} pixel Pixel. * @return {Uint8ClampedArray|Uint8Array|Float32Array|DataView} Data at the pixel location. * @override */ getData(pixel) { const gl = this.helper.getGL(); if (!gl) { return null; } const frameState = this.frameState; if (!frameState) { return null; } const layer = this.getLayer(); const coordinate = apply( frameState.pixelToCoordinateTransform, pixel.slice() ); const viewState = frameState.viewState; const layerExtent = layer.getExtent(); if (layerExtent) { if (!containsCoordinate( fromUserExtent(layerExtent, viewState.projection), coordinate )) { return null; } } const sources = layer.getSources( boundingExtent([coordinate]), viewState.resolution ); let i, source, tileGrid; for (i = sources.length - 1; i >= 0; --i) { source = sources[i]; if (source.getState() === "ready") { tileGrid = source.getTileGridForProjection(viewState.projection); if (source.getWrapX()) { break; } const gridExtent = tileGrid.getExtent(); if (!gridExtent || containsCoordinate(gridExtent, coordinate)) { break; } } } if (i < 0) { return null; } const tileTextureCache = this.tileRepresentationCache; for (let z = tileGrid.getZForResolution(viewState.resolution); z >= tileGrid.getMinZoom(); --z) { const tileCoord = tileGrid.getTileCoordForCoordAndZ(coordinate, z); const cacheKey = getCacheKey(source, tileCoord); if (!tileTextureCache.containsKey(cacheKey)) { continue; } const tileTexture = tileTextureCache.get(cacheKey); const tile = tileTexture.tile; if (tile.getState() === TileState_default.EMPTY) { return null; } if (!tileTexture.loaded) { continue; } const tileOrigin = tileGrid.getOrigin(z); const tileSize = toSize(tileGrid.getTileSize(z)); const tileResolution = tileGrid.getResolution(z); const col = (coordinate[0] - tileOrigin[0]) / tileResolution - tileCoord[1] * tileSize[0]; const row = (tileOrigin[1] - coordinate[1]) / tileResolution - tileCoord[2] * tileSize[1]; return tileTexture.getPixelData(col, row); } return null; } /** * Clean up. * @override */ disposeInternal() { const helper = this.helper; if (helper) { const gl = helper.getGL(); for (const paletteTexture of this.paletteTextures_) { paletteTexture.delete(gl); } this.paletteTextures_.length = 0; gl.deleteProgram(this.program_); delete this.program_; helper.deleteBuffer(this.indices_); } super.disposeInternal(); delete this.indices_; } }; var TileLayer_default = WebGLTileLayerRenderer; // node_modules/ol/webgl/PaletteTexture.js var PaletteTexture = class { /** * @param {string} name The name of the texture. * @param {Uint8Array} data The texture data. */ constructor(name, data) { this.name = name; this.data = data; this.texture_ = null; } /** * @param {WebGLRenderingContext} gl Rendering context. * @return {WebGLTexture} The texture. */ getTexture(gl) { if (!this.texture_) { const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, this.data.length / 4, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.data ); this.texture_ = texture; } return this.texture_; } /** * @param {WebGLRenderingContext} gl Rendering context. */ delete(gl) { if (this.texture_) { gl.deleteTexture(this.texture_); } this.texture_ = null; } }; var PaletteTexture_default = PaletteTexture; // node_modules/ol/expr/gpu.js function computeOperatorFunctionName(operator, context) { return `operator_${operator}_${Object.keys(context.functions).length}`; } function numberToGlsl(v) { const s = v.toString(); return s.includes(".") ? s : s + ".0"; } function arrayToGlsl(array) { if (array.length < 2 || array.length > 4) { throw new Error( "`formatArray` can only output `vec2`, `vec3` or `vec4` arrays." ); } return `vec${array.length}(${array.map(numberToGlsl).join(", ")})`; } function colorToGlsl(color) { const array = asArray(color); const alpha = array.length > 3 ? array[3] : 1; return arrayToGlsl([array[0] / 255, array[1] / 255, array[2] / 255, alpha]); } function sizeToGlsl(size) { const array = toSize(size); return arrayToGlsl(array); } var stringToFloatMap = {}; var stringToFloatCounter = 0; function getStringNumberEquivalent(string) { if (!(string in stringToFloatMap)) { stringToFloatMap[string] = stringToFloatCounter++; } return stringToFloatMap[string]; } function stringToGlsl(string) { return numberToGlsl(getStringNumberEquivalent(string)); } function uniformNameForVariable(variableName) { return "u_var_" + variableName; } function newCompilationContext() { return { variables: {}, properties: {}, functions: {}, bandCount: 0, featureId: false, geometryType: false }; } var GET_BAND_VALUE_FUNC = "getBandValue"; var PALETTE_TEXTURE_ARRAY = "u_paletteTextures"; var FEATURE_ID_PROPERTY_NAME = "featureId"; var GEOMETRY_TYPE_PROPERTY_NAME = "geometryType"; var UNDEFINED_PROP_VALUE = -9999999; function buildExpression(encoded, type, parsingContext, compilationContext) { const expression = parse(encoded, type, parsingContext); return compile(expression, type, compilationContext); } function createCompiler(output) { return (context, expression, type) => { const length = expression.args.length; const args = new Array(length); for (let i = 0; i < length; ++i) { args[i] = compile(expression.args[i], type, context); } return output(args, context); }; } var compilers = { [Ops.Get]: (context, expression) => { const firstArg = ( /** @type {LiteralExpression} */ expression.args[0] ); const propName = ( /** @type {string} */ firstArg.value ); const isExisting = propName in context.properties; if (!isExisting) { context.properties[propName] = { name: propName, type: expression.type }; } return "a_prop_" + propName; }, [Ops.Id]: (context) => { context.featureId = true; return "a_" + FEATURE_ID_PROPERTY_NAME; }, [Ops.GeometryType]: (context) => { context.geometryType = true; return "a_" + GEOMETRY_TYPE_PROPERTY_NAME; }, [Ops.LineMetric]: () => "currentLineMetric", // this variable is assumed to always be present in shaders, default is 0. [Ops.Var]: (context, expression) => { const firstArg = ( /** @type {LiteralExpression} */ expression.args[0] ); const varName = ( /** @type {string} */ firstArg.value ); const isExisting = varName in context.variables; if (!isExisting) { context.variables[varName] = { name: varName, type: expression.type }; } return uniformNameForVariable(varName); }, [Ops.Has]: (context, expression) => { const firstArg = ( /** @type {LiteralExpression} */ expression.args[0] ); const propName = ( /** @type {string} */ firstArg.value ); const isExisting = propName in context.properties; if (!isExisting) { context.properties[propName] = { name: propName, type: expression.type }; } return `(a_prop_${propName} != ${numberToGlsl(UNDEFINED_PROP_VALUE)})`; }, [Ops.Resolution]: () => "u_resolution", [Ops.Zoom]: () => "u_zoom", [Ops.Time]: () => "u_time", [Ops.Any]: createCompiler((compiledArgs) => `(${compiledArgs.join(` || `)})`), [Ops.All]: createCompiler((compiledArgs) => `(${compiledArgs.join(` && `)})`), [Ops.Not]: createCompiler(([value]) => `(!${value})`), [Ops.Equal]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} == ${secondValue})` ), [Ops.NotEqual]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} != ${secondValue})` ), [Ops.GreaterThan]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} > ${secondValue})` ), [Ops.GreaterThanOrEqualTo]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} >= ${secondValue})` ), [Ops.LessThan]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} < ${secondValue})` ), [Ops.LessThanOrEqualTo]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} <= ${secondValue})` ), [Ops.Multiply]: createCompiler( (compiledArgs) => `(${compiledArgs.join(" * ")})` ), [Ops.Divide]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} / ${secondValue})` ), [Ops.Add]: createCompiler((compiledArgs) => `(${compiledArgs.join(" + ")})`), [Ops.Subtract]: createCompiler( ([firstValue, secondValue]) => `(${firstValue} - ${secondValue})` ), [Ops.Clamp]: createCompiler( ([value, min, max]) => `clamp(${value}, ${min}, ${max})` ), [Ops.Mod]: createCompiler(([value, modulo]) => `mod(${value}, ${modulo})`), [Ops.Pow]: createCompiler(([value, power]) => `pow(${value}, ${power})`), [Ops.Abs]: createCompiler(([value]) => `abs(${value})`), [Ops.Floor]: createCompiler(([value]) => `floor(${value})`), [Ops.Ceil]: createCompiler(([value]) => `ceil(${value})`), [Ops.Round]: createCompiler(([value]) => `floor(${value} + 0.5)`), [Ops.Sin]: createCompiler(([value]) => `sin(${value})`), [Ops.Cos]: createCompiler(([value]) => `cos(${value})`), [Ops.Atan]: createCompiler(([firstValue, secondValue]) => { return secondValue !== void 0 ? `atan(${firstValue}, ${secondValue})` : `atan(${firstValue})`; }), [Ops.Sqrt]: createCompiler(([value]) => `sqrt(${value})`), [Ops.Match]: createCompiler((compiledArgs) => { const input = compiledArgs[0]; const fallback = compiledArgs[compiledArgs.length - 1]; let result = null; for (let i = compiledArgs.length - 3; i >= 1; i -= 2) { const match = compiledArgs[i]; const output = compiledArgs[i + 1]; result = `(${input} == ${match} ? ${output} : ${result || fallback})`; } return result; }), [Ops.Between]: createCompiler( ([value, min, max]) => `(${value} >= ${min} && ${value} <= ${max})` ), [Ops.Interpolate]: createCompiler(([exponent, input, ...compiledArgs]) => { let result = ""; for (let i = 0; i < compiledArgs.length - 2; i += 2) { const stop1 = compiledArgs[i]; const output1 = result || compiledArgs[i + 1]; const stop2 = compiledArgs[i + 2]; const output2 = compiledArgs[i + 3]; let ratio; if (exponent === numberToGlsl(1)) { ratio = `(${input} - ${stop1}) / (${stop2} - ${stop1})`; } else { ratio = `(pow(${exponent}, (${input} - ${stop1})) - 1.0) / (pow(${exponent}, (${stop2} - ${stop1})) - 1.0)`; } result = `mix(${output1}, ${output2}, clamp(${ratio}, 0.0, 1.0))`; } return result; }), [Ops.Case]: createCompiler((compiledArgs) => { const fallback = compiledArgs[compiledArgs.length - 1]; let result = null; for (let i = compiledArgs.length - 3; i >= 0; i -= 2) { const condition = compiledArgs[i]; const output = compiledArgs[i + 1]; result = `(${condition} ? ${output} : ${result || fallback})`; } return result; }), [Ops.In]: createCompiler(([needle, ...haystack], context) => { const funcName = computeOperatorFunctionName("in", context); const tests = []; for (let i = 0; i < haystack.length; i += 1) { tests.push(` if (inputValue == ${haystack[i]}) { return true; }`); } context.functions[funcName] = `bool ${funcName}(float inputValue) { ${tests.join("\n")} return false; }`; return `${funcName}(${needle})`; }), [Ops.Array]: createCompiler( (args) => `vec${args.length}(${args.join(", ")})` ), [Ops.Color]: createCompiler((compiledArgs) => { if (compiledArgs.length === 1) { return `vec4(vec3(${compiledArgs[0]} / 255.0), 1.0)`; } if (compiledArgs.length === 2) { return `vec4(vec3(${compiledArgs[0]} / 255.0), ${compiledArgs[1]})`; } const rgb = compiledArgs.slice(0, 3).map((color) => `${color} / 255.0`); if (compiledArgs.length === 3) { return `vec4(${rgb.join(", ")}, 1.0)`; } const alpha = compiledArgs[3]; return `vec4(${rgb.join(", ")}, ${alpha})`; }), [Ops.Band]: createCompiler(([band, xOffset, yOffset], context) => { if (!(GET_BAND_VALUE_FUNC in context.functions)) { let ifBlocks = ""; const bandCount = context.bandCount || 1; for (let i = 0; i < bandCount; i++) { const colorIndex = Math.floor(i / 4); let bandIndex = i % 4; if (i === bandCount - 1 && bandIndex === 1) { bandIndex = 3; } const textureName = `${Uniforms2.TILE_TEXTURE_ARRAY}[${colorIndex}]`; ifBlocks += ` if (band == ${i + 1}.0) { return texture2D(${textureName}, v_textureCoord + vec2(dx, dy))[${bandIndex}]; } `; } context.functions[GET_BAND_VALUE_FUNC] = `float getBandValue(float band, float xOffset, float yOffset) { float dx = xOffset / ${Uniforms2.TEXTURE_PIXEL_WIDTH}; float dy = yOffset / ${Uniforms2.TEXTURE_PIXEL_HEIGHT}; ${ifBlocks} }`; } return `${GET_BAND_VALUE_FUNC}(${band}, ${xOffset ?? "0.0"}, ${yOffset ?? "0.0"})`; }), [Ops.Palette]: (context, expression) => { const [index, ...colors] = expression.args; const numColors = colors.length; const palette = new Uint8Array(numColors * 4); for (let i = 0; i < colors.length; i++) { const parsedValue = ( /** @type {string | Array} */ /** @type {LiteralExpression} */ colors[i].value ); const color = asArray(parsedValue); const offset = i * 4; palette[offset] = color[0]; palette[offset + 1] = color[1]; palette[offset + 2] = color[2]; palette[offset + 3] = color[3] * 255; } if (!context.paletteTextures) { context.paletteTextures = []; } const paletteName = `${PALETTE_TEXTURE_ARRAY}[${context.paletteTextures.length}]`; const paletteTexture = new PaletteTexture_default(paletteName, palette); context.paletteTextures.push(paletteTexture); const compiledIndex = compile(index, NumberType, context); return `texture2D(${paletteName}, vec2((${compiledIndex} + 0.5) / ${numColors}.0, 0.5))`; } // TODO: unimplemented // Ops.Number // Ops.String // Ops.Coalesce // Ops.Concat // Ops.ToString }; function compile(expression, returnType, context) { if (expression instanceof CallExpression) { const compiler = compilers[expression.operator]; if (compiler === void 0) { throw new Error( `No compiler defined for this operator: ${JSON.stringify( expression.operator )}` ); } return compiler(context, expression, returnType); } if ((expression.type & NumberType) > 0) { return numberToGlsl( /** @type {number} */ expression.value ); } if ((expression.type & BooleanType) > 0) { return expression.value.toString(); } if ((expression.type & StringType) > 0) { return stringToGlsl(expression.value.toString()); } if ((expression.type & ColorType) > 0) { return colorToGlsl( /** @type {Array | string} */ expression.value ); } if ((expression.type & NumberArrayType) > 0) { return arrayToGlsl( /** @type {Array} */ expression.value ); } if ((expression.type & SizeType) > 0) { return sizeToGlsl( /** @type {number|import('../size.js').Size} */ expression.value ); } throw new Error( `Unexpected expression ${expression.value} (expected type ${typeName( returnType )})` ); } // node_modules/ol/render/webgl/compileUtil.js function expressionToGlsl(compilationContext, value, expectedType) { const parsingContext = newParsingContext(); return buildExpression( value, expectedType, parsingContext, compilationContext ); } function packColor(color) { const array = asArray(color); const r = array[0] * 256; const g = array[1]; const b = array[2] * 256; const a = Math.round(array[3] * 255); return [r + g, b + a]; } var UNPACK_COLOR_FN = `vec4 unpackColor(vec2 packedColor) { return vec4( fract(floor(packedColor[0] / 256.0) / 256.0), fract(packedColor[0] / 256.0), fract(floor(packedColor[1] / 256.0) / 256.0), fract(packedColor[1] / 256.0) ); }`; function getGlslSizeFromType(type) { if (type === ColorType || type === SizeType) { return 2; } if (type === NumberArrayType) { return 4; } return 1; } function getGlslTypeFromType(type) { const size = getGlslSizeFromType(type); if (size > 1) { return ( /** @type {'vec2'|'vec3'|'vec4'} */ `vec${size}` ); } return "float"; } function applyContextToBuilder(builder, context) { for (const varName in context.variables) { const variable = context.variables[varName]; const uniformName = uniformNameForVariable(variable.name); let glslType = getGlslTypeFromType(variable.type); if (variable.type === ColorType) { glslType = "vec4"; } builder.addUniform(uniformName, glslType); } for (const propName in context.properties) { const property = context.properties[propName]; const glslType = getGlslTypeFromType(property.type); const attributeName = `a_prop_${property.name}`; if (property.type === ColorType) { builder.addAttribute( attributeName, glslType, `unpackColor(${attributeName})`, "vec4" ); builder.addVertexShaderFunction(UNPACK_COLOR_FN); } else { builder.addAttribute(attributeName, glslType); } } for (const functionName in context.functions) { builder.addVertexShaderFunction(context.functions[functionName]); builder.addFragmentShaderFunction(context.functions[functionName]); } } function generateUniformsFromContext(context, variables) { const uniforms = {}; for (const varName in context.variables) { const variable = context.variables[varName]; const uniformName = uniformNameForVariable(variable.name); uniforms[uniformName] = () => { const value = variables[variable.name]; if (typeof value === "number") { return value; } if (typeof value === "boolean") { return value ? 1 : 0; } if (variable.type === ColorType) { const color = [...asArray(value || "#eee")]; color[0] /= 255; color[1] /= 255; color[2] /= 255; color[3] ?? (color[3] = 1); return color; } if (typeof value === "string") { return getStringNumberEquivalent(value); } return value; }; } return uniforms; } function generateAttributesFromContext(context) { const attributes = {}; for (const propName in context.properties) { const property = context.properties[propName]; const callback = (feature) => { const value = feature.get(property.name); if (property.type === ColorType) { return packColor([...asArray(value || "#eee")]); } if (typeof value === "string") { return getStringNumberEquivalent(value); } if (typeof value === "boolean") { return value ? 1 : 0; } return value; }; attributes[`prop_${property.name}`] = { size: getGlslSizeFromType(property.type), callback }; } return attributes; } export { ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW, Buffer_default, DefaultUniform, AttributeType, Layer_default2 as Layer_default, Uniforms2 as Uniforms, Attributes, TileLayer_default, numberToGlsl, colorToGlsl, getStringNumberEquivalent, stringToGlsl, uniformNameForVariable, newCompilationContext, PALETTE_TEXTURE_ARRAY, FEATURE_ID_PROPERTY_NAME, GEOMETRY_TYPE_PROPERTY_NAME, UNDEFINED_PROP_VALUE, expressionToGlsl, getGlslSizeFromType, getGlslTypeFromType, applyContextToBuilder, generateUniformsFromContext, generateAttributesFromContext }; //# sourceMappingURL=chunk-PZZAKLYX.js.map