@genome-spy/app 1.0.0 → 1.1.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 (39) hide show
  1. package/dist/SharedReadCache-Ey5QIiPM.js +207 -0
  2. package/dist/{agentApi-Z65dw-sD.js → agentApi-sPuuT0KS.js} +3573 -3485
  3. package/dist/agentApi.es.js +1550 -1461
  4. package/dist/agentShared.es.js +2 -2
  5. package/dist/{canvas2d-t_N10CeW.js → canvas2d-MXaFeZnP.js} +4 -4
  6. package/dist/{canvas2d-DiPQvNtZ.js → canvas2d-iDK4BC5j.js} +4 -4
  7. package/dist/{debug-CVAlrcZt.js → debug-BlqDxTw3.js} +2 -2
  8. package/dist/{debug-DP4WzTNo.js → debug-DbigmdrK.js} +2 -2
  9. package/dist/esm-C-6g-SkZ.js +791 -0
  10. package/dist/{esm-L53qjcYH.js → esm-CJeszW-t.js} +344 -250
  11. package/dist/esm-CjkeZi__.js +238 -0
  12. package/dist/index.es.js +2896 -2896
  13. package/dist/index.js +303 -304
  14. package/dist/{order-R043xTpC.js → order-B4uR9Q04.js} +1 -1
  15. package/dist/{order-BkYCnwD7.js → order-BSPy5DI8.js} +1 -1
  16. package/dist/{rasterExport-C_FcNBkC.js → rasterExport-B62RmAK1.js} +3 -3
  17. package/dist/{rasterExport-Z7gs5346.js → rasterExport-DQH3hVg_.js} +3 -3
  18. package/dist/{rasterization-_-9JmSas.js → rasterization-B05bDo5e.js} +15 -18
  19. package/dist/rasterization-CFogVB3B.js +50 -0
  20. package/dist/{renderCanvas2D-IM-A9DYG.js → renderCanvas2D-Bdv-B4wj.js} +15 -15
  21. package/dist/{renderCanvas2D-DK1c9TFK.js → renderCanvas2D-ChdoHGrU.js} +15 -15
  22. package/dist/scalePosition-ByvlXaML.js +11 -0
  23. package/dist/schema.json +7 -0
  24. package/dist/{svg-PabUdcDi.js → svg-DHsq1RpV.js} +13 -13
  25. package/dist/{svg-DW3tfUmm.js → svg-N3tj05-e.js} +13 -13
  26. package/dist/{svgRasterizer-B6YtWLJs.js → svgRasterizer-CYVDlt5z.js} +2 -2
  27. package/dist/{svgRasterizer-BEVDyyS3.js → svgRasterizer-CvCBlxLj.js} +2 -2
  28. package/dist/{viewIdentityRegistry-BW415b3o.js → viewIdentityRegistry-BDKkEjXl.js} +1 -1
  29. package/dist/{viewIdentityRegistry-_F0E7nkA.js → viewIdentityRegistry-BIYd4TE0.js} +1 -1
  30. package/dist/{viewSelectors-KtD-QSN0.js → viewSelectors-DDLW-byr.js} +80 -50
  31. package/dist/{viewSelectors-DYz-PhTO.js → viewSelectors-j-F9XwsE.js} +80 -50
  32. package/dist/{viewUtils-BZGPseMx.js → viewUtils-JX6CMEYH.js} +1212 -1211
  33. package/dist/{webgl-BKSGqHaz.js → webgl-DdmOwEH0.js} +107 -86
  34. package/dist/{webgl-tdKf9SlZ.js → webgl-Dw8xqZpX.js} +107 -86
  35. package/package.json +7 -9
  36. package/LICENSE +0 -21
  37. package/dist/AbortablePromiseCache-BTmAcN-t.js +0 -96
  38. package/dist/esm-BiqrFjMh.js +0 -443
  39. package/dist/esm-DtNElqRr.js +0 -462
@@ -3143,28 +3143,49 @@ var gc = class {
3143
3143
  }
3144
3144
  this.registerBatch(e);
3145
3145
  }
3146
- }, Sc = "#define PI 3.141593\n\nuniform View {\n /** Offset in \"unit\" units */\n mediump vec2 uViewOffset;\n mediump vec2 uViewScale;\n /** Size of the logical viewport in pixels, i.e., the view */\n mediump vec2 uViewportSize;\n mediump vec4 uLogicalVisibleRect;\n lowp vec2 uCullByVisibleRange;\n lowp float uDevicePixelRatio;\n // TODO: Views with opacity less than 1.0 should be rendered into a texture\n // that is rendered with the specified opacity.\n lowp float uViewOpacity;\n bool uPickingEnabled;\n};\n\n\n/**\n * Maps a coordinate on the unit scale to a normalized device coordinate.\n * (0, 0) is at the bottom left corner.\n */\nvec4 unitToNdc(vec2 coord) {\n return vec4((coord * uViewScale + uViewOffset) * 2.0 - 1.0, 0.0, 1.0);\n}\n\nvec4 unitToNdc(float x, float y) {\n return unitToNdc(vec2(x, y));\n}\n\nvec4 pixelsToNdc(vec2 coord) {\n return unitToNdc(coord / uViewportSize);\n}\n\nvec4 pixelsToNdc(float x, float y) {\n return pixelsToNdc(vec2(x, y));\n}\n\n/** Applies logical pixel offsets to a position in unit coordinates. */\nvec2 applyOffset(vec2 pos, vec2 offset) {\n return pos + vec2(offset.x, -offset.y) / uViewportSize;\n}\n\nbool isOutsideVisibleRange(vec2 pos) {\n return (uCullByVisibleRange.x > 0.5 &&\n (pos.x < uLogicalVisibleRect.x ||\n pos.x > uLogicalVisibleRect.z)) ||\n (uCullByVisibleRange.y > 0.5 &&\n (pos.y < uLogicalVisibleRect.y ||\n pos.y > uLogicalVisibleRect.w));\n}\n\nfloat linearstep(float edge0, float edge1, float x) {\n return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n}\n\nconst highp uint HASH_EMPTY_KEY = 0xffffffffu;\n\nhighp uint hash32(highp uint key) {\n highp uint v = key;\n v ^= v >> 16u;\n v *= 0x7feb352du;\n v ^= v >> 15u;\n v *= 0x846ca68bu;\n v ^= v >> 16u;\n return v;\n}\n\nbool isEmptyHashTexture(highp usampler2D s) {\n // Empty selections are encoded as a single empty hash slot.\n ivec2 texSize = textureSize(s, 0);\n return texSize.x == 1 && texSize.y == 1 && texelFetch(s, ivec2(0, 0), 0).r == HASH_EMPTY_KEY;\n}\n\nbool hashContainsTexture(highp usampler2D s, highp uint value) {\n ivec2 texSize = textureSize(s, 0);\n highp uint width = uint(texSize.x);\n highp uint size = width * uint(texSize.y);\n highp uint mask = size - 1u;\n highp uint index = hash32(value) & mask;\n\n for (highp uint probe = 0u; probe < size; probe += 1u) {\n ivec2 coord = ivec2(int(index % width), int(index / width));\n highp uint entry = texelFetch(s, coord, 0).r;\n if (entry == value) {\n return true;\n }\n if (entry == HASH_EMPTY_KEY) {\n return false;\n }\n index = (index + 1u) & mask;\n }\n\n return false;\n}\n\n/**\n * Calculates a gamma for antialiasing opacity based on the color.\n */\nfloat getGammaForColor(vec3 rgb) {\n return mix(\n 1.25,\n 0.75,\n // RGB should be linearized but this is good enough for now\n smoothstep(0.0, 1.0, dot(rgb, vec3(0.299, 0.587, 0.114))));\n}\n\n// Fragment shader stuff ////////////////////////////////////////////////////////\n\n// TODO: include the following only in fragment shaders\n\n/**\n * Specialized linearstep for doing antialiasing\n */\nfloat distanceToRatio(float d) {\n return clamp(d * uDevicePixelRatio + 0.5, 0.0, 1.0);\n}\n\nvec4 distanceToColor(float d, vec4 fill, vec4 stroke, vec4 background, float halfStrokeWidth) {\n if (halfStrokeWidth > 0.0) {\n // Distance to stroke's edge. Negative inside the stroke.\n float sd = abs(d) - halfStrokeWidth;\n return mix(\n stroke,\n d <= 0.0 ? fill : background,\n distanceToRatio(sd));\n } else {\n return mix(background, fill, distanceToRatio(-d));\n }\n}\n", Cc = "uniform highp float uZero;\n\n// Utils ------------\n\nvec3 getDiscreteColor(sampler2D s, int index) {\n return texelFetch(s, ivec2(index % textureSize(s, 0).x, 0), 0).rgb;\n}\n\nvec3 getInterpolatedColor(sampler2D s, float unitValue) {\n return texture(s, vec2(unitValue, 0.0)).rgb;\n}\n\nfloat clampToRange(float value, vec2 range) {\n return clamp(value, min(range[0], range[1]), max(range[0], range[1]));\n}\n\n// Scales ------------\n// Based on d3 scales: https://github.com/d3/d3-scale\n\nfloat scaleIdentity(float value) {\n return value;\n}\n\nfloat scaleIdentity(uint value) {\n return float(value);\n}\n\nfloat scaleLinear(float value, vec2 domain, vec2 range) {\n float domainSpan = domain[1] - domain[0];\n float rangeSpan = range[1] - range[0];\n return (value - domain[0]) / domainSpan * rangeSpan + range[0];\n}\n\nfloat scaleLog(float value, vec2 domain, vec2 range, float base) {\n // y = m log(x) + b \n // TODO: Perf optimization: precalculate log domain in js.\n // TODO: Reversed domain, etc\n return scaleLinear(log(value) / log(base), log(domain) / log(base), range);\n}\n\nfloat symlog(float value, float constant) {\n // WARNING: emulating log1p with log(x + 1). Small numbers are likely to\n // have significant precision problems.\n return sign(value) * log(abs(value / constant) + 1.0);\n}\n\nfloat scaleSymlog(float value, vec2 domain, vec2 range, float constant) {\n return scaleLinear(\n symlog(value, constant),\n vec2(symlog(domain[0], constant), symlog(domain[1], constant)),\n range\n );\n}\n\nfloat scalePow(float value, vec2 domain, vec2 range, float exponent) {\n // y = mx^k + b\n // TODO: Perf optimization: precalculate pow domain in js.\n // TODO: Reversed domain, etc\n return scaleLinear(\n pow(abs(value), exponent) * sign(value),\n pow(abs(domain), vec2(exponent)) * sign(domain),\n range\n );\n}\n\n// TODO: scaleThreshold\n// TODO: scaleQuantile (special case of threshold scale)\n\n// TODO: domainExtent should be uint\nfloat scaleBand(uint value, vec2 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n float n = domainExtent[1] - domainExtent[0];\n\n // This fix departs from Vega and d3: https://github.com/vega/vega/issues/3357#issuecomment-1063253596\n paddingInner = int(n) > 1 ? paddingInner : 0.0;\n\n // Adapted from: https://github.com/d3/d3-scale/blob/master/src/band.js\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n return start + (float(value) - domainExtent[0]) * step + bandwidth * band;\n}\n\nconst int lowBits = 12;\nconst float lowDivisor = pow(2.0, float(lowBits));\nconst uint lowMask = uint(lowDivisor - 1.0);\n\nvec2 splitUint(uint value) {\n uint valueLo = value & lowMask;\n uint valueHi = value - valueLo;\n return vec2(float(valueHi), float(valueLo));\n}\n\n/**\n * High precision variant of scaleBand for index/locus scales\n */\nfloat scaleBandHp(uint value, vec3 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n vec2 domainStart = domainExtent.xy;\n float n = domainExtent[2];\n\n // The following computation is identical for every vertex. Could be done on the JS side.\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n // Split into to values with each having a reduced number of significant digits\n // to mitigate the lack of precision in float32 calculations.\n vec2 splitValue = splitUint(value);\n\n // Using max to prevent the shader compiler from wrecking the precision.\n // Othwewise the compiler could optimize the sum of the four terms into\n // some equivalent form that does premature rounding.\n float inf = 1.0 / uZero;\n float hi = max(splitValue[0] - domainStart[0], -inf);\n float lo = max(splitValue[1] - domainStart[1], -inf);\n\n return dot(vec4(start, hi, lo, bandwidth), vec4(1.0, step, step, band));\n}\n\n/**\n * High precision variant of scaleBand for index/locus scales for large\n * domains where 32bit uints are not sufficient to represent the domain.\n */\nfloat scaleBandHp(uvec2 value, vec3 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n vec2 domainStart = domainExtent.xy;\n float n = domainExtent[2];\n\n // The following computation is identical for every vertex. Could be done on the JS side.\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n // Split into to values with each having a reduced number of significant digits\n // to mitigate the lack of precision in float32 calculations.\n vec2 splitValue = vec2(float(value[0]) * lowDivisor, float(value[1]));\n\n // Using max to prevent the shader compiler from wrecking the precision.\n // Othwewise the compiler could optimize the sum of the four terms into\n // some equivalent form that does premature rounding.\n float inf = 1.0 / uZero;\n float hi = max(splitValue[0] - domainStart[0], -inf);\n float lo = max(splitValue[1] - domainStart[1], -inf);\n\n return dot(vec4(start, hi, lo, bandwidth), vec4(1.0, step, step, band));\n}\n", wc = "\n/** Describes where a sample facet should be shown. */\nstruct SampleFacetPosition {\n float pos;\n float height;\n};\n\n// ----------------------------------------------------------------------------\n\n#if !defined(SAMPLE_FACET_UNIFORM) && !defined(SAMPLE_FACET_TEXTURE)\n\nSampleFacetPosition getSampleFacetPos() {\n return SampleFacetPosition(0.0, 1.0);\n}\n\n#elif defined(SAMPLE_FACET_UNIFORM)\n\n/**\n * Location and height of the band on the Y axis on a normalized [0, 1] scale.\n * Elements: position, height\n */\nuniform vec2 uSampleFacet;\n\nSampleFacetPosition getSampleFacetPos() {\n return SampleFacetPosition(\n 1.0 - uSampleFacet.x - uSampleFacet.y,\n uSampleFacet.y\n );\n}\n\n#elif defined(SAMPLE_FACET_TEXTURE)\n\nuniform sampler2D uSampleFacetTexture;\n\nSampleFacetPosition getSampleFacetPos() {\n vec2 texel = texelFetch(\n uSampleFacetTexture,\n ivec2(int(attr_facetIndex), 0),\n 0\n ).rg;\n return SampleFacetPosition(\n 1.0 - texel.x - texel.y,\n texel.y\n );\n}\n\n#endif\n\nvec2 applySampleFacet(vec2 pos) {\n SampleFacetPosition facetPos = getSampleFacetPos();\n return vec2(pos.x, facetPos.pos + pos.y * facetPos.height);\n}\n", Tc = "/*\n * Based on concepts presented at:\n * https://webglfundamentals.org/webgl/lessons/webgl-picking.html\n * https://deck.gl/docs/developer-guide/custom-layers/picking\n */\n\nout highp vec4 vPickingColor;\n\n/**\n * Passes the unique id to the fragment shader as a color if picking is enabled.\n * Returns true if picking is enabled.\n */\nbool setupPicking() {\n if (uPickingEnabled) {\n#ifdef uniqueId_DEFINED\n uint id = attr_uniqueId;\n vPickingColor = vec4(\n ivec4(id >> 0, id >> 8, id >> 16, id >> 24) & 0xFF\n ) / float(0xFF);\n#else\n vPickingColor = vec4(1.0);\n#endif\n return true;\n }\n return false;\n}\n", Ec = "in highp vec4 vPickingColor;\n", Dc = .5;
3146
+ }, Sc = "#define PI 3.141593\n\nuniform View {\n /** Offset in \"unit\" units */\n mediump vec2 uViewOffset;\n mediump vec2 uViewScale;\n /** Size of the logical viewport in pixels, i.e., the view */\n mediump vec2 uViewportSize;\n mediump vec4 uLogicalVisibleRect;\n lowp vec2 uCullByVisibleRange;\n lowp float uDevicePixelRatio;\n // TODO: Views with opacity less than 1.0 should be rendered into a texture\n // that is rendered with the specified opacity.\n lowp float uViewOpacity;\n bool uPickingEnabled;\n};\n\n\n/**\n * Maps a coordinate on the unit scale to a normalized device coordinate.\n * (0, 0) is at the bottom left corner.\n */\nvec4 unitToNdc(vec2 coord) {\n return vec4((coord * uViewScale + uViewOffset) * 2.0 - 1.0, 0.0, 1.0);\n}\n\nvec4 unitToNdc(float x, float y) {\n return unitToNdc(vec2(x, y));\n}\n\nvec4 pixelsToNdc(vec2 coord) {\n return unitToNdc(coord / uViewportSize);\n}\n\nvec4 pixelsToNdc(float x, float y) {\n return pixelsToNdc(vec2(x, y));\n}\n\n/** Applies logical pixel offsets to a position in unit coordinates. */\nvec2 applyOffset(vec2 pos, vec2 offset) {\n return pos + vec2(offset.x, -offset.y) / uViewportSize;\n}\n\nbool isOutsideVisibleRange(vec2 pos) {\n return (uCullByVisibleRange.x > 0.5 &&\n (pos.x < uLogicalVisibleRect.x ||\n pos.x > uLogicalVisibleRect.z)) ||\n (uCullByVisibleRange.y > 0.5 &&\n (pos.y < uLogicalVisibleRect.y ||\n pos.y > uLogicalVisibleRect.w));\n}\n\nfloat linearstep(float edge0, float edge1, float x) {\n return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n}\n\nconst highp uint HASH_EMPTY_KEY = 0xffffffffu;\n\nhighp uint hash32(highp uint key) {\n highp uint v = key;\n v ^= v >> 16u;\n v *= 0x7feb352du;\n v ^= v >> 15u;\n v *= 0x846ca68bu;\n v ^= v >> 16u;\n return v;\n}\n\nbool isEmptyHashTexture(highp usampler2D s) {\n // Empty selections are encoded as a single empty hash slot.\n ivec2 texSize = textureSize(s, 0);\n return texSize.x == 1 && texSize.y == 1 && texelFetch(s, ivec2(0, 0), 0).r == HASH_EMPTY_KEY;\n}\n\nbool hashContainsTexture(highp usampler2D s, highp uint value) {\n ivec2 texSize = textureSize(s, 0);\n highp uint width = uint(texSize.x);\n highp uint size = width * uint(texSize.y);\n highp uint mask = size - 1u;\n highp uint index = hash32(value) & mask;\n\n for (highp uint probe = 0u; probe < size; probe += 1u) {\n ivec2 coord = ivec2(int(index % width), int(index / width));\n highp uint entry = texelFetch(s, coord, 0).r;\n if (entry == value) {\n return true;\n }\n if (entry == HASH_EMPTY_KEY) {\n return false;\n }\n index = (index + 1u) & mask;\n }\n\n return false;\n}\n\n/**\n * Calculates a gamma for antialiasing opacity based on the color.\n */\nfloat getGammaForColor(vec3 rgb) {\n return mix(\n 1.25,\n 0.75,\n // RGB should be linearized but this is good enough for now\n smoothstep(0.0, 1.0, dot(rgb, vec3(0.299, 0.587, 0.114))));\n}\n\n// Fragment shader stuff ////////////////////////////////////////////////////////\n\n// TODO: include the following only in fragment shaders\n\n/**\n * Specialized linearstep for doing antialiasing\n */\nfloat distanceToRatio(float d) {\n return clamp(d * uDevicePixelRatio + 0.5, 0.0, 1.0);\n}\n\nvec4 distanceToColor(float d, vec4 fill, vec4 stroke, vec4 background, float halfStrokeWidth) {\n if (halfStrokeWidth > 0.0) {\n // Distance to stroke's edge. Negative inside the stroke.\n float sd = abs(d) - halfStrokeWidth;\n return mix(\n stroke,\n d <= 0.0 ? fill : background,\n distanceToRatio(sd));\n } else {\n return mix(background, fill, distanceToRatio(-d));\n }\n}\n", Cc = "uniform highp float uZero;\n\n// Utils ------------\n\nvec3 getDiscreteColor(sampler2D s, int index) {\n return texelFetch(s, ivec2(index % textureSize(s, 0).x, 0), 0).rgb;\n}\n\nvec3 getInterpolatedColor(sampler2D s, float unitValue) {\n return texture(s, vec2(unitValue, 0.0)).rgb;\n}\n\nfloat clampToRange(float value, vec2 range) {\n return clamp(value, min(range[0], range[1]), max(range[0], range[1]));\n}\n\n// Scales ------------\n// Based on d3 scales: https://github.com/d3/d3-scale\n\nfloat scaleIdentity(float value) {\n return value;\n}\n\nfloat scaleIdentity(uint value) {\n return float(value);\n}\n\nfloat scaleLinear(float value, vec2 domain, vec2 range) {\n float domainSpan = domain[1] - domain[0];\n float rangeSpan = range[1] - range[0];\n return (value - domain[0]) / domainSpan * rangeSpan + range[0];\n}\n\nfloat scaleLog(float value, vec2 domain, vec2 range, float base) {\n // y = m log(x) + b \n // TODO: Perf optimization: precalculate log domain in js.\n // TODO: Reversed domain, etc\n return scaleLinear(log(value) / log(base), log(domain) / log(base), range);\n}\n\nfloat symlog(float value, float constant) {\n // WARNING: emulating log1p with log(x + 1). Small numbers are likely to\n // have significant precision problems.\n return sign(value) * log(abs(value / constant) + 1.0);\n}\n\nfloat scaleSymlog(float value, vec2 domain, vec2 range, float constant) {\n return scaleLinear(\n symlog(value, constant),\n vec2(symlog(domain[0], constant), symlog(domain[1], constant)),\n range\n );\n}\n\nfloat scalePow(float value, vec2 domain, vec2 range, float exponent) {\n // y = mx^k + b\n // TODO: Perf optimization: precalculate pow domain in js.\n // TODO: Reversed domain, etc\n return scaleLinear(\n pow(abs(value), exponent) * sign(value),\n pow(abs(domain), vec2(exponent)) * sign(domain),\n range\n );\n}\n\n// TODO: scaleThreshold\n// TODO: scaleQuantile (special case of threshold scale)\n\n// TODO: domainExtent should be uint\nfloat scaleBand(uint value, vec2 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n float n = domainExtent[1] - domainExtent[0];\n\n // This fix departs from Vega and d3: https://github.com/vega/vega/issues/3357#issuecomment-1063253596\n paddingInner = int(n) > 1 ? paddingInner : 0.0;\n\n // Adapted from: https://github.com/d3/d3-scale/blob/master/src/band.js\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n return start + (float(value) - domainExtent[0]) * step + bandwidth * band;\n}\n\nconst int lowBits = 12;\nconst float lowDivisor = pow(2.0, float(lowBits));\nconst uint lowMask = uint(lowDivisor - 1.0);\n\nvec2 splitUint(uint value) {\n uint valueLo = value & lowMask;\n uint valueHi = value - valueLo;\n return vec2(float(valueHi), float(valueLo));\n}\n\n/**\n * High precision variant of scaleBand for index/locus scales\n */\nfloat scaleBandHp(uint value, vec3 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n vec2 domainStart = domainExtent.xy;\n float n = domainExtent[2];\n\n // The following computation is identical for every vertex. Could be done on the JS side.\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n // Split into to values with each having a reduced number of significant digits\n // to mitigate the lack of precision in float32 calculations.\n vec2 splitValue = splitUint(value);\n\n // Using max to prevent the shader compiler from wrecking the precision.\n // Othwewise the compiler could optimize the sum of the four terms into\n // some equivalent form that does premature rounding.\n float inf = 1.0 / uZero;\n float hi = max(splitValue[0] - domainStart[0], -inf);\n float lo = max(splitValue[1] - domainStart[1], -inf);\n\n return dot(vec4(start, hi, lo, bandwidth), vec4(1.0, step, step, band));\n}\n\n/**\n * High precision variant of scaleBand for index/locus scales for large\n * domains where 32bit uints are not sufficient to represent the domain.\n */\nfloat scaleBandHp(uvec2 value, vec3 domainExtent, vec2 range,\n float paddingInner, float paddingOuter,\n float align, float band) {\n\n // TODO: reverse\n float start = range[0];\n float stop = range[1];\n float rangeSpan = stop - start;\n\n vec2 domainStart = domainExtent.xy;\n float n = domainExtent[2];\n\n // The following computation is identical for every vertex. Could be done on the JS side.\n float step = rangeSpan / max(1.0, n - paddingInner + paddingOuter * 2.0);\n start += (rangeSpan - step * (n - paddingInner)) * align;\n float bandwidth = step * (1.0 - paddingInner);\n\n // Split into to values with each having a reduced number of significant digits\n // to mitigate the lack of precision in float32 calculations.\n vec2 splitValue = vec2(float(value[0]) * lowDivisor, float(value[1]));\n\n // Using max to prevent the shader compiler from wrecking the precision.\n // Othwewise the compiler could optimize the sum of the four terms into\n // some equivalent form that does premature rounding.\n float inf = 1.0 / uZero;\n float hi = max(splitValue[0] - domainStart[0], -inf);\n float lo = max(splitValue[1] - domainStart[1], -inf);\n\n return dot(vec4(start, hi, lo, bandwidth), vec4(1.0, step, step, band));\n}\n", wc = "\n/** Describes where a sample facet should be shown. */\nstruct SampleFacetPosition {\n float pos;\n float height;\n};\n\n// ----------------------------------------------------------------------------\n\n#if !defined(SAMPLE_FACET_UNIFORM) && !defined(SAMPLE_FACET_TEXTURE)\n\nSampleFacetPosition getSampleFacetPos() {\n return SampleFacetPosition(0.0, 1.0);\n}\n\n#elif defined(SAMPLE_FACET_UNIFORM)\n\n/**\n * Location and height of the band on the Y axis on a normalized [0, 1] scale.\n * Elements: position, height\n */\nuniform vec2 uSampleFacet;\n\nSampleFacetPosition getSampleFacetPos() {\n return SampleFacetPosition(\n 1.0 - uSampleFacet.x - uSampleFacet.y,\n uSampleFacet.y\n );\n}\n\n#elif defined(SAMPLE_FACET_TEXTURE)\n\nuniform sampler2D uSampleFacetTexture;\n\nSampleFacetPosition getSampleFacetPos() {\n vec2 texel = texelFetch(\n uSampleFacetTexture,\n ivec2(int(attr_facetIndex), 0),\n 0\n ).rg;\n return SampleFacetPosition(\n 1.0 - texel.x - texel.y,\n texel.y\n );\n}\n\n#endif\n\nvec2 applySampleFacet(vec2 pos) {\n SampleFacetPosition facetPos = getSampleFacetPos();\n return vec2(pos.x, facetPos.pos + pos.y * facetPos.height);\n}\n", Tc = "/*\n * Based on concepts presented at:\n * https://webglfundamentals.org/webgl/lessons/webgl-picking.html\n * https://deck.gl/docs/developer-guide/custom-layers/picking\n */\n\nout highp vec4 vPickingColor;\n\n/**\n * Passes the unique id to the fragment shader as a color if picking is enabled.\n * Returns true if picking is enabled.\n */\nbool setupPicking() {\n if (uPickingEnabled) {\n#ifdef uniqueId_DEFINED\n uint id = attr_uniqueId;\n vPickingColor = vec4(\n ivec4(id >> 0, id >> 8, id >> 16, id >> 24) & 0xFF\n ) / float(0xFF);\n#else\n vPickingColor = vec4(1.0);\n#endif\n return true;\n }\n return false;\n}\n", Ec = "in highp vec4 vPickingColor;\n";
3147
+ //#endregion
3148
+ //#region ../core/src/rendering/webgl/gl/uniformBlocks.js
3149
+ function Dc(e, t, n) {
3150
+ let r = t.uniformBlockSpec, i = r.blockSpecs[n], a = t;
3151
+ return i && i.size % 16 != 0 && (a = {
3152
+ ...t,
3153
+ uniformBlockSpec: {
3154
+ ...r,
3155
+ blockSpecs: {
3156
+ ...r.blockSpecs,
3157
+ [n]: {
3158
+ ...i,
3159
+ size: Math.ceil(i.size / 16) * 16
3160
+ }
3161
+ }
3162
+ }
3163
+ }), Za(e, a, n);
3164
+ }
3165
+ //#endregion
3166
+ //#region ../core/src/rendering/renderingConstants.js
3167
+ var Oc = .5;
3147
3168
  //#endregion
3148
3169
  //#region ../core/src/rendering/webgl/textFont.js
3149
- function Oc(e) {
3170
+ function kc(e) {
3150
3171
  let t = e.unitView.context.textMetrics, n = e.properties;
3151
3172
  return t.getFont(n.font, n.fontStyle, n.fontWeight);
3152
3173
  }
3153
3174
  //#endregion
3154
3175
  //#region ../core/src/rendering/webgl/marks/webGlMark.js
3155
- var kc = "SAMPLE_FACET_UNIFORM", Ac = "SAMPLE_FACET_TEXTURE", jc = "uSelectionTexture_", Mc = {
3176
+ var Ac = "SAMPLE_FACET_UNIFORM", jc = "SAMPLE_FACET_TEXTURE", Mc = "uSelectionTexture_", Nc = {
3156
3177
  all: 0,
3157
3178
  matching: 1,
3158
3179
  nonmatching: 2
3159
3180
  };
3160
- function Nc(e, t) {
3181
+ function Pc(e, t) {
3161
3182
  return e.replace(/#pragma orderGuard(?:[ \t]*\r?\n){0,2}/, t);
3162
3183
  }
3163
- var Pc = class {
3184
+ var Fc = class {
3164
3185
  #e = [];
3165
3186
  #t = !1;
3166
3187
  constructor(e, t, n) {
3167
- this.mark = e, this._glHelper = t, this._rendererResources = n, this.bufferInfo = void 0, this.bytesPerElement = /* @__PURE__ */ new Map(), this.programInfo = void 0, this.vertexArrayInfo = void 0, this.viewUniformInfo = void 0, this.markUniformInfo = void 0, this.markUniformsAltered = !0, this.selectionTextureOps = [], this.scaleResolutionDisposers = [], this.rangeMap = new Fc();
3188
+ this.mark = e, this._glHelper = t, this._rendererResources = n, this.bufferInfo = void 0, this.bytesPerElement = /* @__PURE__ */ new Map(), this.programInfo = void 0, this.vertexArrayInfo = void 0, this.viewUniformInfo = void 0, this.markUniformInfo = void 0, this.markUniformsAltered = !0, this.selectionTextureOps = [], this.scaleResolutionDisposers = [], this.rangeMap = new Ic();
3168
3189
  }
3169
3190
  get unitView() {
3170
3191
  return this.mark.unitView;
@@ -3179,7 +3200,7 @@ var Pc = class {
3179
3200
  return this.mark.properties;
3180
3201
  }
3181
3202
  get font() {
3182
- return Oc(this.mark);
3203
+ return kc(this.mark);
3183
3204
  }
3184
3205
  get opaque() {
3185
3206
  return !1;
@@ -3197,8 +3218,8 @@ var Pc = class {
3197
3218
  this.#n();
3198
3219
  }
3199
3220
  getSampleFacetMode() {
3200
- if (this.encoders.facetIndex) return Ac;
3201
- if (this.unitView.usesSampleFacetRendering()) return kc;
3221
+ if (this.encoders.facetIndex) return jc;
3222
+ if (this.unitView.usesSampleFacetRendering()) return Ac;
3202
3223
  }
3203
3224
  createAndLinkShaders(r, i, s = []) {
3204
3225
  let l = this.getAttributes(), u = this.encoders, f = this.mark.getOrder(), p = this.getSampleFacetMode(), m = !!this.properties.cullByVisibleRange;
@@ -3222,7 +3243,7 @@ var Pc = class {
3222
3243
  this.registerMarkUniformValue(n, { expr: e }, (e) => e.uniqueId ?? 0);
3223
3244
  }), g.push(`bool ${os}${e}() {\n return ${as}${e} != 0u && ${as}${e} == ${o};\n}`), g.push(`bool ${ss}${e}() {\n return ${as}${e} == 0u;\n}`);
3224
3245
  } else if (le(i)) {
3225
- let n = jc + t(e);
3246
+ let n = Mc + t(e);
3226
3247
  g.push(`// Selection texture\nuniform highp usampler2D ${n};`);
3227
3248
  let a = this.glHelper, s = a.selectionTextures;
3228
3249
  this.selectionTextureOps.push(() => {
@@ -3230,7 +3251,7 @@ var Pc = class {
3230
3251
  if (!i) throw Error(`Bug: no selection texture found for "${e}"!`);
3231
3252
  J(this.programInfo, { [n]: i });
3232
3253
  });
3233
- let c = jc + e;
3254
+ let c = Mc + e;
3234
3255
  g.push(`bool ${os}${e}() {\n return hashContainsTexture(${c}, ${o});\n}`), g.push(`bool ${ss}${e}() {\n return isEmptyHashTexture(${c});\n}`), a.createSelectionTexture(i), r.watchExpression(e, () => {
3235
3256
  let t = r.getValue(e);
3236
3257
  a.createSelectionTexture(t), this.unitView.context.animator.requestRender();
@@ -3311,7 +3332,7 @@ var Pc = class {
3311
3332
  return ${e};\n}`);
3312
3333
  }
3313
3334
  let oe = "precision highp float;\nprecision highp int;", ue = (e) => e.replace("#pragma markUniforms", x.join("\n"));
3314
- s = s.map(ue), r = ue(r), i = ue(i), r = ((e) => Nc(e, f ? " if (uOrderMode != 0 &&\n (((uOrderMode & 3) == 1) != isOrderMatch())) {\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }" : ""))(r);
3335
+ s = s.map(ue), r = ue(r), i = ue(i), r = ((e) => Pc(e, f ? " if (uOrderMode != 0 &&\n (((uOrderMode & 3) == 1) != isOrderMatch())) {\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }" : ""))(r);
3315
3336
  let de = [
3316
3337
  oe,
3317
3338
  h,
@@ -3342,7 +3363,7 @@ var Pc = class {
3342
3363
  let t = /* @__PURE__ */ Error("Cannot create shader program: " + e.message);
3343
3364
  throw t.view = this.unitView, t;
3344
3365
  }
3345
- this.programInfo = io(this.gl, this.programStatus.program), delete this.programStatus, this.viewUniformInfo = Za(this.gl, this.programInfo, "View"), this.markUniformInfo = Za(this.gl, this.programInfo, "Mark"), this.gl.useProgram(this.programInfo.program), J(this.programInfo, {
3366
+ this.programInfo = io(this.gl, this.programStatus.program), delete this.programStatus, this.viewUniformInfo = Dc(this.gl, this.programInfo, "View"), this.markUniformInfo = Dc(this.gl, this.programInfo, "Mark"), this.gl.useProgram(this.programInfo.program), J(this.programInfo, {
3346
3367
  uSampleFacet: [0, 1],
3347
3368
  uZero: 0
3348
3369
  });
@@ -3419,7 +3440,7 @@ var Pc = class {
3419
3440
  this.markUniformsAltered ? ($a(this.gl, this.programInfo, this.markUniformInfo), this.markUniformsAltered = !1) : Qa(this.gl, this.programInfo, this.markUniformInfo);
3420
3441
  }
3421
3442
  setOrderPass(e, t = !1) {
3422
- eo(this.markUniformInfo, { uOrderMode: Mc[e] | (t ? 4 : 0) }), this.markUniformsAltered = !0;
3443
+ eo(this.markUniformInfo, { uOrderMode: Nc[e] | (t ? 4 : 0) }), this.markUniformsAltered = !0;
3423
3444
  }
3424
3445
  prepareRender(e) {
3425
3446
  let t = this.glHelper, n = this.gl, r = [];
@@ -3430,7 +3451,7 @@ var Pc = class {
3430
3451
  let i = t.rangeTextures.get(n.scale);
3431
3452
  i && r.push(() => J(this.programInfo, { [is + e]: i }));
3432
3453
  }
3433
- r.push(...this.selectionTextureOps), this.getSampleFacetMode() == Ac && r.push(() => {
3454
+ r.push(...this.selectionTextureOps), this.getSampleFacetMode() == jc && r.push(() => {
3434
3455
  let t = e.placement?.source;
3435
3456
  if (!t) throw Error("No placement source available.");
3436
3457
  J(this.programInfo, { uSampleFacetTexture: this.glHelper.getPlacementTexture(t) });
@@ -3469,9 +3490,9 @@ var Pc = class {
3469
3490
  d.count && a(d);
3470
3491
  };
3471
3492
  }
3472
- setViewport(e, t, n, r, i, a = Dc) {
3493
+ setViewport(e, t, n, r, i, a = Oc) {
3473
3494
  n = n.flatten();
3474
- let o = this.gl, s = this.properties, c = a, l = a, u, d = Ic(e, n, s.clip === "never" ? void 0 : r, !1), f = d.coords;
3495
+ let o = this.gl, s = this.properties, c = a, l = a, u, d = Lc(e, n, s.clip === "never" ? void 0 : r, !1), f = d.coords;
3475
3496
  if (d.requiresScissor) {
3476
3497
  if (!f.isDefined()) return !1;
3477
3498
  let r = [
@@ -3494,12 +3515,12 @@ var Pc = class {
3494
3515
  return eo(this.viewUniformInfo, {
3495
3516
  ...u,
3496
3517
  uViewportSize: [n.width, n.height],
3497
- uLogicalVisibleRect: Lc(n, i),
3518
+ uLogicalVisibleRect: Rc(n, i),
3498
3519
  uCullByVisibleRange: [+(s.cullByVisibleRange === !0 || s.cullByVisibleRange === "x"), +(s.cullByVisibleRange === !0 || s.cullByVisibleRange === "y")],
3499
3520
  uDevicePixelRatio: t
3500
3521
  }), $a(this.gl, this.programInfo, this.viewUniformInfo), !0;
3501
3522
  }
3502
- }, Fc = class extends x {
3523
+ }, Ic = class extends x {
3503
3524
  constructor() {
3504
3525
  super([], JSON.stringify);
3505
3526
  }
@@ -3516,7 +3537,7 @@ var Pc = class {
3516
3537
  for (let [t, n] of e.entries()) Object.assign(this.get(t), n);
3517
3538
  }
3518
3539
  };
3519
- function Ic(e, t, n, r = !0) {
3540
+ function Lc(e, t, n, r = !0) {
3520
3541
  if (!n || !n.clipX && !n.clipY) return {
3521
3542
  requiresScissor: !1,
3522
3543
  coords: t
@@ -3533,7 +3554,7 @@ function Ic(e, t, n, r = !0) {
3533
3554
  coords: i.flatten()
3534
3555
  };
3535
3556
  }
3536
- function Lc(e, t) {
3557
+ function Rc(e, t) {
3537
3558
  let n = t?.clipX ? (t.rect.x - e.x) / e.width : 0, r = t?.clipX ? (t.rect.x2 - e.x) / e.width : 1;
3538
3559
  return [
3539
3560
  n,
@@ -3544,7 +3565,7 @@ function Lc(e, t) {
3544
3565
  }
3545
3566
  //#endregion
3546
3567
  //#region ../core/src/rendering/webgl/marks/arrow.js
3547
- var Rc = Math.PI / 180, zc = 1e-6, Bc = 1, Vc = 90, Hc = ["triangle", "open"], Uc = ["inside", "outside"], Wc = class extends Pc {
3568
+ var zc = Math.PI / 180, Bc = 1e-6, Vc = 1, Hc = 90, Uc = ["triangle", "open"], Wc = ["inside", "outside"], Gc = class extends Fc {
3548
3569
  getAttributes() {
3549
3570
  return [
3550
3571
  "uniqueId",
@@ -3572,7 +3593,7 @@ var Rc = Math.PI / 180, zc = 1e-6, Bc = 1, Vc = 90, Hc = ["triangle", "open"], U
3572
3593
  finalizeGraphicsInitialization() {
3573
3594
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
3574
3595
  let e = this.properties;
3575
- this.registerMarkUniformValue("uHeadSlope", e.headAngle, Kc), this.registerMarkUniformValue("uHeadNotchSlope", e.headNotchAngle, Kc), this.registerMarkUniformValue("uHeadShape", e.headShape, (e) => Gc(Hc, e)), this.registerMarkUniformValue("uMinSize", e.minSize), this.registerMarkUniformValue("uHeadWidth", e.headWidth), this.registerMarkUniformValue("uStartNotch", e.startNotch), this.registerMarkUniformValue("uMinStemLength", e.minStemLength), this.registerMarkUniformValue("uHeadSpacing", e.headSpacing ?? -1, qc), this.registerMarkUniformValue("uStem", e.stem), this.registerMarkUniformValue("uHeadPlacement", e.headPlacement, (e) => Gc(Uc, e));
3596
+ this.registerMarkUniformValue("uHeadSlope", e.headAngle, qc), this.registerMarkUniformValue("uHeadNotchSlope", e.headNotchAngle, qc), this.registerMarkUniformValue("uHeadShape", e.headShape, (e) => Kc(Uc, e)), this.registerMarkUniformValue("uMinSize", e.minSize), this.registerMarkUniformValue("uHeadWidth", e.headWidth), this.registerMarkUniformValue("uStartNotch", e.startNotch), this.registerMarkUniformValue("uMinStemLength", e.minStemLength), this.registerMarkUniformValue("uHeadSpacing", e.headSpacing ?? -1, Jc), this.registerMarkUniformValue("uStem", e.stem), this.registerMarkUniformValue("uHeadPlacement", e.headPlacement, (e) => Kc(Wc, e));
3576
3597
  }
3577
3598
  updateGraphicsData(e) {
3578
3599
  let t = e.getItemCount(), n = new vc({
@@ -3595,25 +3616,25 @@ var Rc = Math.PI / 180, zc = 1e-6, Bc = 1, Vc = 90, Hc = ["triangle", "open"], U
3595
3616
  }, e);
3596
3617
  }
3597
3618
  };
3598
- function Gc(e, t) {
3619
+ function Kc(e, t) {
3599
3620
  let n = e.indexOf(t);
3600
3621
  if (n < 0) throw Error(`Unsupported arrow mark value: ${t}`);
3601
3622
  return n;
3602
3623
  }
3603
- function Kc(e) {
3604
- return Math.max(Math.tan(Math.min(Math.max(e, Bc), Vc) * Rc), zc);
3605
- }
3606
3624
  function qc(e) {
3625
+ return Math.max(Math.tan(Math.min(Math.max(e, Vc), Hc) * zc), Bc);
3626
+ }
3627
+ function Jc(e) {
3607
3628
  return e ?? -1;
3608
3629
  }
3609
3630
  //#endregion
3610
3631
  //#region ../core/src/rendering/webgl/marks/link.vertex.glsl
3611
- var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\n/** The distance from the line center to the direction of normal in pixels */\nout float vNormalLengthInPixels;\n\nflat out float vGamma;\n\n// Centerline distance from the rendered endpoint baseline; negative disables fading.\nout float vFadeDistance;\n\nconst int SHAPE_ARC = 0;\nconst int SHAPE_DOME = 1;\nconst int SHAPE_DIAGONAL = 2;\nconst int SHAPE_LINE = 3;\nconst int ORIENT_VERTICAL = 0;\nconst int ORIENT_HORIZONTAL = 1;\n\nfloat distanceFromLine(vec2 pointOnLine1, vec2 pointOnLine2, vec2 point) {\n vec2 a = point - pointOnLine1;\n vec2 b = pointOnLine2 - pointOnLine1;\n vec2 proj = dot(a, b) / dot(b, b) * b;\n return length(a - proj);\n}\n\nbool isInsideViewport(vec2 point, float marginFactor) {\n vec2 margin = uViewportSize * vec2(marginFactor);\n return point.x >= -margin.x\n && point.x <= uViewportSize.x + margin.x\n && point.y >= -margin.y\n && point.y <= uViewportSize.y + margin.y;\n}\n\nfloat inverseSmoothstep(float t) {\n t = clamp(t, 0.0, 1.0);\n // The chord-axis coordinate of ARC/DOME follows the smoothstep curve.\n return 0.5 - sin(asin(1.0 - 2.0 * t) / 3.0);\n}\n\n/**\n * Remaps the parameter t to concentrate vertices to the part that is visible in the viewport.\n * This keeps the tightly bent endpoints smooth even when zooming in very close.\n */\nfloat remapVisibleChordParameter(\n float stripT,\n float chordStart,\n float chordEnd,\n float viewportLength\n) {\n // Concentrate samples in the viewport-visible chord interval without dropping the rest.\n float chordMin = min(chordStart, chordEnd);\n float chordMax = max(chordStart, chordEnd);\n float chordSpan = chordMax - chordMin;\n\n if (chordSpan <= 0.0) {\n return 0.0;\n }\n\n float visibleChordMin = max(chordMin, 0.0);\n float visibleChordMax = min(chordMax, viewportLength);\n\n if (visibleChordMax <= visibleChordMin) {\n return stripT;\n }\n\n float visibleTMin = inverseSmoothstep((visibleChordMin - chordMin) / chordSpan);\n float visibleTMax = inverseSmoothstep((visibleChordMax - chordMin) / chordSpan);\n float visibleTSpan = visibleTMax - visibleTMin;\n float offscreenTSpan = visibleTMin + (1.0 - visibleTMax);\n\n if (offscreenTSpan <= 0.0) {\n return stripT;\n }\n\n float visibleShare = clamp(0.75 + (1.0 - visibleTSpan) * 0.2, 0.75, 0.95);\n float offscreenShare = 1.0 - visibleShare;\n float leftShare = offscreenShare * visibleTMin / offscreenTSpan;\n float rightShare = offscreenShare * (1.0 - visibleTMax) / offscreenTSpan;\n\n if (stripT <= leftShare) {\n return leftShare > 0.0 ? mix(0.0, visibleTMin, stripT / leftShare) : visibleTMin;\n }\n\n float visibleStart = leftShare;\n float visibleEnd = visibleStart + visibleShare;\n\n if (stripT <= visibleEnd) {\n return visibleShare > 0.0\n ? mix(visibleTMin, visibleTMax, (stripT - visibleStart) / visibleShare)\n : visibleTMin;\n }\n\n return rightShare > 0.0\n ? mix(visibleTMax, 1.0, (stripT - visibleEnd) / rightShare)\n : visibleTMax;\n}\n\nvoid clampChordToViewport(inout vec2 p1, inout vec2 p4, inout float chordLength) {\n if (chordLength > uMaxChordLength) {\n vec2 chordVector = p4 - p1;\n vec2 unitChordVector = normalize(chordVector);\n\n if (isInsideViewport(p1, 2.0)) {\n chordLength = uMaxChordLength;\n p4 = p1 + unitChordVector * uMaxChordLength;\n } else if (isInsideViewport(p4, 2.0)) {\n chordLength = uMaxChordLength;\n p1 = p4 - unitChordVector * uMaxChordLength;\n }\n }\n}\n\nvoid clampDomeApex(inout vec2 p1, inout vec2 p4, int orient) {\n if (orient == ORIENT_VERTICAL) {\n if (p4.x > 0.0) {\n p1.x = max(p1.x, -p4.x);\n }\n if (p1.x < uViewportSize.x) {\n p4.x = min(p4.x, 2.0 * uViewportSize.x - p1.x);\n }\n } else {\n if (p4.y > 0.0) {\n p1.y = max(p1.y, -p4.y);\n }\n if (p1.y < uViewportSize.y) {\n p4.y = min(p4.y, 2.0 * uViewportSize.y - p1.y);\n }\n }\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float pixelSize = 1.0 / uDevicePixelRatio;\n float opacity = getScaled_opacity() * uViewOpacity;\n\n // The bezier's control points\n vec2 p1, p2, p3, p4;\n\n vec2 a = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n ) * uViewportSize;\n vec2 b = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n ) * uViewportSize;\n\n if (uShape <= SHAPE_DOME) {\n if (uShape == SHAPE_DOME) {\n vec2 height = vec2(0.0);\n if (uOrient == ORIENT_VERTICAL) {\n p1 = vec2(min(a.x, b.x), b.y);\n p4 = vec2(max(a.x, b.x), b.y);\n height = vec2(0.0, a.y - b.y);\n\n float chordLength = length(p4 - p1);\n clampChordToViewport(p1, p4, chordLength);\n if (uClampApex) {\n clampDomeApex(p1, p4, ORIENT_VERTICAL);\n }\n\n } else {\n p1 = vec2(b.x, min(a.y, b.y));\n p4 = vec2(b.x, max(a.y, b.y));\n height = vec2(a.x - b.x, 0.0);\n\n float chordLength = length(p4 - p1);\n clampChordToViewport(p1, p4, chordLength);\n if (uClampApex) {\n clampDomeApex(p1, p4, ORIENT_HORIZONTAL);\n }\n }\n\n vec2 controlOffset = height / 0.75;\n p2 = p1 + controlOffset;\n p3 = p4 + controlOffset;\n\n } if (uShape == SHAPE_ARC) {\n p1 = a;\n p4 = b;\n\n vec2 chordVector = p4 - p1;\n vec2 unitChordVector = normalize(chordVector);\n vec2 chordNormal = vec2(-unitChordVector.y, unitChordVector.x);\n float chordLength = length(chordVector);\n clampChordToViewport(p1, p4, chordLength);\n\n float height = max(\n chordLength / 2.0 * uArcHeightFactor,\n uMinArcHeight\n );\n\n // This is a bit poor approximation of a circular arc, but it's probably enough for most purposes.\n // TODO: Consider a more sophisticated approach: https://stackoverflow.com/a/44829356/1547896\n vec2 controlOffset = chordNormal * height / 0.75;\n p2 = p1 + controlOffset;\n p3 = p4 + controlOffset;\n }\n\n } else if (uShape == SHAPE_DIAGONAL) {\n if (uOrient == ORIENT_VERTICAL) {\n p1 = a;\n p2 = vec2(a.x, (a.y + b.y) / 2.0);\n p3 = vec2(b.x, (a.y + b.y) / 2.0);\n p4 = b;\n } else {\n p1 = a;\n p2 = vec2((a.x + b.x) / 2.0, a.y);\n p3 = vec2((a.x + b.x) / 2.0, b.y);\n p4 = b;\n }\n } else if (uShape == SHAPE_LINE) {\n p1 = a;\n p2 = (a + b) / 2.0;\n p3 = p2;\n p4 = b;\n }\n\n vec2 strip = vec2(\n float(gl_VertexID / 2) / float(uSegmentBreaks),\n float(gl_VertexID % 2) - 0.5\n );\n\n float t = strip.x;\n\n if (uShape == SHAPE_DOME) {\n if (uOrient == ORIENT_VERTICAL) {\n t = remapVisibleChordParameter(strip.x, p1.x, p4.x, uViewportSize.x);\n } else {\n t = remapVisibleChordParameter(strip.x, p1.y, p4.y, uViewportSize.y);\n }\n } else if (uShape == SHAPE_ARC) {\n if (a.y == b.y) {\n t = remapVisibleChordParameter(strip.x, p1.x, p4.x, uViewportSize.x);\n } else if (a.x == b.x) {\n t = remapVisibleChordParameter(strip.x, p1.y, p4.y, uViewportSize.y);\n }\n }\n\n vec2 p;\n vec2 tangent;\n\n // de Casteljau evaluation keeps the cubic stable for long chords.\n vec2 q1 = mix(p1, p2, t);\n vec2 q2 = mix(p2, p3, t);\n vec2 q3 = mix(p3, p4, t);\n\n vec2 r1 = mix(q1, q2, t);\n vec2 r2 = mix(q2, q3, t);\n\n p = mix(r1, r2, t);\n tangent = 3.0 * (r2 - r1);\n\n tangent = normalize(tangent);\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float size = getScaled_size();\n\n // Avoid artifacts in very thin lines by clamping the size and adjusting opacity respectively\n if (size < pixelSize) {\n opacity *= size / pixelSize;\n size = pixelSize;\n }\n\n // Handle minimum picking size or add an extra pixel to the stroke width to accommodate edge antialiasing\n float paddedSize = uPickingEnabled\n ? max(size, uMinPickingSize)\n : size + pixelSize;\n\n vNormalLengthInPixels = strip.y * paddedSize;\n \n vFadeDistance = -1.0;\n if ((uShape == SHAPE_ARC || uShape == SHAPE_DOME) &&\n uArcFadingDistance[0] > 0.0 &&\n uArcFadingDistance[1] > 0.0\n#ifdef CONDITIONAL_ORDER\n && (!uNoFadingOnSecondPass || (uOrderMode & 4) == 0)\n#endif\n )\n {\n vFadeDistance = distanceFromLine(p1, p4, p);\n // Keep fully faded triangles collapsed to avoid fragment processing.\n if (1.0 - smoothstep(uArcFadingDistance[0], uArcFadingDistance[1], vFadeDistance) <= 0.0) {\n vNormalLengthInPixels = 0.0;\n }\n }\n\n // Extrude\n p += normal * vNormalLengthInPixels;\n\n gl_Position = pixelsToNdc(p);\n\n vec3 color = getScaled_color();\n\n vColor = vec4(color * opacity, opacity);\n\n vGamma = getGammaForColor(color);\n\n vSize = paddedSize;\n\n setupPicking();\n}\n", Yc = "flat in vec4 vColor;\nflat in float vSize;\nin float vNormalLengthInPixels;\nflat in float vGamma;\nin float vFadeDistance;\n\nout lowp vec4 fragColor;\n\nvoid main(void) {\n float dpr = uDevicePixelRatio;\n\n float distance = abs(vNormalLengthInPixels);\n float opacity = clamp(((vSize / 2.0 - distance) * dpr), 0.0, 1.0);\n\n opacity = pow(opacity, vGamma);\n\n if (vFadeDistance >= 0.0) {\n opacity *= 1.0 - smoothstep(uArcFadingDistance[0], uArcFadingDistance[1], vFadeDistance);\n }\n if (opacity <= 0.0) {\n discard;\n }\n\n fragColor = vColor * opacity;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", Xc = "layout(std140) uniform Mark {\n uniform float uArcHeightFactor;\n\n /** Make very small arcs visible */\n uniform float uMinArcHeight;\n\n /** The minimum stroke width in pixels when rendering into the picking buffer */\n uniform float uMinPickingSize;\n\n uniform int uShape;\n uniform int uOrient;\n uniform bool uClampApex;\n\n // In pixels\n uniform float uMaxChordLength;\n // In pixels\n uniform vec2 uArcFadingDistance;\n uniform bool uNoFadingOnSecondPass;\n\n uniform int uSegmentBreaks;\n\n#pragma markUniforms\n};\n", Zc = [
3632
+ var Yc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\n/** The distance from the line center to the direction of normal in pixels */\nout float vNormalLengthInPixels;\n\nflat out float vGamma;\n\n// Centerline distance from the rendered endpoint baseline; negative disables fading.\nout float vFadeDistance;\n\nconst int SHAPE_ARC = 0;\nconst int SHAPE_DOME = 1;\nconst int SHAPE_DIAGONAL = 2;\nconst int SHAPE_LINE = 3;\nconst int ORIENT_VERTICAL = 0;\nconst int ORIENT_HORIZONTAL = 1;\n\nfloat distanceFromLine(vec2 pointOnLine1, vec2 pointOnLine2, vec2 point) {\n vec2 a = point - pointOnLine1;\n vec2 b = pointOnLine2 - pointOnLine1;\n vec2 proj = dot(a, b) / dot(b, b) * b;\n return length(a - proj);\n}\n\nbool isInsideViewport(vec2 point, float marginFactor) {\n vec2 margin = uViewportSize * vec2(marginFactor);\n return point.x >= -margin.x\n && point.x <= uViewportSize.x + margin.x\n && point.y >= -margin.y\n && point.y <= uViewportSize.y + margin.y;\n}\n\nfloat inverseSmoothstep(float t) {\n t = clamp(t, 0.0, 1.0);\n // The chord-axis coordinate of ARC/DOME follows the smoothstep curve.\n return 0.5 - sin(asin(1.0 - 2.0 * t) / 3.0);\n}\n\n/**\n * Remaps the parameter t to concentrate vertices to the part that is visible in the viewport.\n * This keeps the tightly bent endpoints smooth even when zooming in very close.\n */\nfloat remapVisibleChordParameter(\n float stripT,\n float chordStart,\n float chordEnd,\n float viewportLength\n) {\n // Concentrate samples in the viewport-visible chord interval without dropping the rest.\n float chordMin = min(chordStart, chordEnd);\n float chordMax = max(chordStart, chordEnd);\n float chordSpan = chordMax - chordMin;\n\n if (chordSpan <= 0.0) {\n return 0.0;\n }\n\n float visibleChordMin = max(chordMin, 0.0);\n float visibleChordMax = min(chordMax, viewportLength);\n\n if (visibleChordMax <= visibleChordMin) {\n return stripT;\n }\n\n float visibleTMin = inverseSmoothstep((visibleChordMin - chordMin) / chordSpan);\n float visibleTMax = inverseSmoothstep((visibleChordMax - chordMin) / chordSpan);\n float visibleTSpan = visibleTMax - visibleTMin;\n float offscreenTSpan = visibleTMin + (1.0 - visibleTMax);\n\n if (offscreenTSpan <= 0.0) {\n return stripT;\n }\n\n float visibleShare = clamp(0.75 + (1.0 - visibleTSpan) * 0.2, 0.75, 0.95);\n float offscreenShare = 1.0 - visibleShare;\n float leftShare = offscreenShare * visibleTMin / offscreenTSpan;\n float rightShare = offscreenShare * (1.0 - visibleTMax) / offscreenTSpan;\n\n if (stripT <= leftShare) {\n return leftShare > 0.0 ? mix(0.0, visibleTMin, stripT / leftShare) : visibleTMin;\n }\n\n float visibleStart = leftShare;\n float visibleEnd = visibleStart + visibleShare;\n\n if (stripT <= visibleEnd) {\n return visibleShare > 0.0\n ? mix(visibleTMin, visibleTMax, (stripT - visibleStart) / visibleShare)\n : visibleTMin;\n }\n\n return rightShare > 0.0\n ? mix(visibleTMax, 1.0, (stripT - visibleEnd) / rightShare)\n : visibleTMax;\n}\n\nvoid clampChordToViewport(inout vec2 p1, inout vec2 p4, inout float chordLength) {\n if (chordLength > uMaxChordLength) {\n vec2 chordVector = p4 - p1;\n vec2 unitChordVector = normalize(chordVector);\n\n if (isInsideViewport(p1, 2.0)) {\n chordLength = uMaxChordLength;\n p4 = p1 + unitChordVector * uMaxChordLength;\n } else if (isInsideViewport(p4, 2.0)) {\n chordLength = uMaxChordLength;\n p1 = p4 - unitChordVector * uMaxChordLength;\n }\n }\n}\n\nvoid clampDomeApex(inout vec2 p1, inout vec2 p4, int orient) {\n if (orient == ORIENT_VERTICAL) {\n if (p4.x > 0.0) {\n p1.x = max(p1.x, -p4.x);\n }\n if (p1.x < uViewportSize.x) {\n p4.x = min(p4.x, 2.0 * uViewportSize.x - p1.x);\n }\n } else {\n if (p4.y > 0.0) {\n p1.y = max(p1.y, -p4.y);\n }\n if (p1.y < uViewportSize.y) {\n p4.y = min(p4.y, 2.0 * uViewportSize.y - p1.y);\n }\n }\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float pixelSize = 1.0 / uDevicePixelRatio;\n float opacity = getScaled_opacity() * uViewOpacity;\n\n // The bezier's control points\n vec2 p1, p2, p3, p4;\n\n vec2 a = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n ) * uViewportSize;\n vec2 b = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n ) * uViewportSize;\n\n if (uShape <= SHAPE_DOME) {\n if (uShape == SHAPE_DOME) {\n vec2 height = vec2(0.0);\n if (uOrient == ORIENT_VERTICAL) {\n p1 = vec2(min(a.x, b.x), b.y);\n p4 = vec2(max(a.x, b.x), b.y);\n height = vec2(0.0, a.y - b.y);\n\n float chordLength = length(p4 - p1);\n clampChordToViewport(p1, p4, chordLength);\n if (uClampApex) {\n clampDomeApex(p1, p4, ORIENT_VERTICAL);\n }\n\n } else {\n p1 = vec2(b.x, min(a.y, b.y));\n p4 = vec2(b.x, max(a.y, b.y));\n height = vec2(a.x - b.x, 0.0);\n\n float chordLength = length(p4 - p1);\n clampChordToViewport(p1, p4, chordLength);\n if (uClampApex) {\n clampDomeApex(p1, p4, ORIENT_HORIZONTAL);\n }\n }\n\n vec2 controlOffset = height / 0.75;\n p2 = p1 + controlOffset;\n p3 = p4 + controlOffset;\n\n } if (uShape == SHAPE_ARC) {\n p1 = a;\n p4 = b;\n\n vec2 chordVector = p4 - p1;\n vec2 unitChordVector = normalize(chordVector);\n vec2 chordNormal = vec2(-unitChordVector.y, unitChordVector.x);\n float chordLength = length(chordVector);\n clampChordToViewport(p1, p4, chordLength);\n\n float height = max(\n chordLength / 2.0 * uArcHeightFactor,\n uMinArcHeight\n );\n\n // This is a bit poor approximation of a circular arc, but it's probably enough for most purposes.\n // TODO: Consider a more sophisticated approach: https://stackoverflow.com/a/44829356/1547896\n vec2 controlOffset = chordNormal * height / 0.75;\n p2 = p1 + controlOffset;\n p3 = p4 + controlOffset;\n }\n\n } else if (uShape == SHAPE_DIAGONAL) {\n if (uOrient == ORIENT_VERTICAL) {\n p1 = a;\n p2 = vec2(a.x, (a.y + b.y) / 2.0);\n p3 = vec2(b.x, (a.y + b.y) / 2.0);\n p4 = b;\n } else {\n p1 = a;\n p2 = vec2((a.x + b.x) / 2.0, a.y);\n p3 = vec2((a.x + b.x) / 2.0, b.y);\n p4 = b;\n }\n } else if (uShape == SHAPE_LINE) {\n p1 = a;\n p2 = (a + b) / 2.0;\n p3 = p2;\n p4 = b;\n }\n\n vec2 strip = vec2(\n float(gl_VertexID / 2) / float(uSegmentBreaks),\n float(gl_VertexID % 2) - 0.5\n );\n\n float t = strip.x;\n\n if (uShape == SHAPE_DOME) {\n if (uOrient == ORIENT_VERTICAL) {\n t = remapVisibleChordParameter(strip.x, p1.x, p4.x, uViewportSize.x);\n } else {\n t = remapVisibleChordParameter(strip.x, p1.y, p4.y, uViewportSize.y);\n }\n } else if (uShape == SHAPE_ARC) {\n if (a.y == b.y) {\n t = remapVisibleChordParameter(strip.x, p1.x, p4.x, uViewportSize.x);\n } else if (a.x == b.x) {\n t = remapVisibleChordParameter(strip.x, p1.y, p4.y, uViewportSize.y);\n }\n }\n\n vec2 p;\n vec2 tangent;\n\n // de Casteljau evaluation keeps the cubic stable for long chords.\n vec2 q1 = mix(p1, p2, t);\n vec2 q2 = mix(p2, p3, t);\n vec2 q3 = mix(p3, p4, t);\n\n vec2 r1 = mix(q1, q2, t);\n vec2 r2 = mix(q2, q3, t);\n\n p = mix(r1, r2, t);\n tangent = 3.0 * (r2 - r1);\n\n tangent = normalize(tangent);\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float size = getScaled_size();\n\n // Avoid artifacts in very thin lines by clamping the size and adjusting opacity respectively\n if (size < pixelSize) {\n opacity *= size / pixelSize;\n size = pixelSize;\n }\n\n // Handle minimum picking size or add an extra pixel to the stroke width to accommodate edge antialiasing\n float paddedSize = uPickingEnabled\n ? max(size, uMinPickingSize)\n : size + pixelSize;\n\n vNormalLengthInPixels = strip.y * paddedSize;\n \n vFadeDistance = -1.0;\n if ((uShape == SHAPE_ARC || uShape == SHAPE_DOME) &&\n uArcFadingDistance[0] > 0.0 &&\n uArcFadingDistance[1] > 0.0\n#ifdef CONDITIONAL_ORDER\n && (!uNoFadingOnSecondPass || (uOrderMode & 4) == 0)\n#endif\n )\n {\n vFadeDistance = distanceFromLine(p1, p4, p);\n // Keep fully faded triangles collapsed to avoid fragment processing.\n if (1.0 - smoothstep(uArcFadingDistance[0], uArcFadingDistance[1], vFadeDistance) <= 0.0) {\n vNormalLengthInPixels = 0.0;\n }\n }\n\n // Extrude\n p += normal * vNormalLengthInPixels;\n\n gl_Position = pixelsToNdc(p);\n\n vec3 color = getScaled_color();\n\n vColor = vec4(color * opacity, opacity);\n\n vGamma = getGammaForColor(color);\n\n vSize = paddedSize;\n\n setupPicking();\n}\n", Xc = "flat in vec4 vColor;\nflat in float vSize;\nin float vNormalLengthInPixels;\nflat in float vGamma;\nin float vFadeDistance;\n\nout lowp vec4 fragColor;\n\nvoid main(void) {\n float dpr = uDevicePixelRatio;\n\n float distance = abs(vNormalLengthInPixels);\n float opacity = clamp(((vSize / 2.0 - distance) * dpr), 0.0, 1.0);\n\n opacity = pow(opacity, vGamma);\n\n if (vFadeDistance >= 0.0) {\n opacity *= 1.0 - smoothstep(uArcFadingDistance[0], uArcFadingDistance[1], vFadeDistance);\n }\n if (opacity <= 0.0) {\n discard;\n }\n\n fragColor = vColor * opacity;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", Zc = "layout(std140) uniform Mark {\n uniform float uArcHeightFactor;\n\n /** Make very small arcs visible */\n uniform float uMinArcHeight;\n\n /** The minimum stroke width in pixels when rendering into the picking buffer */\n uniform float uMinPickingSize;\n\n uniform int uShape;\n uniform int uOrient;\n uniform bool uClampApex;\n\n // In pixels\n uniform float uMaxChordLength;\n // In pixels\n uniform vec2 uArcFadingDistance;\n uniform bool uNoFadingOnSecondPass;\n\n uniform int uSegmentBreaks;\n\n#pragma markUniforms\n};\n", Qc = [
3612
3633
  "arc",
3613
3634
  "dome",
3614
3635
  "diagonal",
3615
3636
  "line"
3616
- ], Qc = ["vertical", "horizontal"], $c = class extends Pc {
3637
+ ], $c = ["vertical", "horizontal"], el = class extends Fc {
3617
3638
  constructor(e, t, n) {
3618
3639
  super(e, t, n), this._baseInstanceExt = void 0;
3619
3640
  }
@@ -3635,12 +3656,12 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3635
3656
  ];
3636
3657
  }
3637
3658
  initializeGraphics() {
3638
- super.initializeGraphics(), this._baseInstanceExt = this.gl.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"), this.createAndLinkShaders(Jc, Yc, [Xc]);
3659
+ super.initializeGraphics(), this._baseInstanceExt = this.gl.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"), this.createAndLinkShaders(Yc, Xc, [Zc]);
3639
3660
  }
3640
3661
  finalizeGraphicsInitialization() {
3641
3662
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
3642
3663
  let e = this.properties;
3643
- this.registerMarkUniformValue("uArcFadingDistance", e.arcFadingDistance, (e) => e || [0, 0]), this.registerMarkUniformValue("uArcHeightFactor", e.arcHeightFactor), this.registerMarkUniformValue("uMinArcHeight", e.minArcHeight), this.registerMarkUniformValue("uMinPickingSize", e.minPickingSize), this.registerMarkUniformValue("uShape", e.linkShape, (e) => Zc.indexOf(e)), this.registerMarkUniformValue("uOrient", e.orient, (e) => Qc.indexOf(e)), this.registerMarkUniformValue("uClampApex", e.clampApex, (e) => !!e), this.registerMarkUniformValue("uMaxChordLength", e.maxChordLength), this.registerMarkUniformValue("uSegmentBreaks", e.segments, (e) => e), this.registerMarkUniformValue("uNoFadingOnSecondPass", e.noFadingOnSecondPass, (e) => !!e);
3664
+ this.registerMarkUniformValue("uArcFadingDistance", e.arcFadingDistance, (e) => e || [0, 0]), this.registerMarkUniformValue("uArcHeightFactor", e.arcHeightFactor), this.registerMarkUniformValue("uMinArcHeight", e.minArcHeight), this.registerMarkUniformValue("uMinPickingSize", e.minPickingSize), this.registerMarkUniformValue("uShape", e.linkShape, (e) => Qc.indexOf(e)), this.registerMarkUniformValue("uOrient", e.orient, (e) => $c.indexOf(e)), this.registerMarkUniformValue("uClampApex", e.clampApex, (e) => !!e), this.registerMarkUniformValue("uMaxChordLength", e.maxChordLength), this.registerMarkUniformValue("uSegmentBreaks", e.segments, (e) => e), this.registerMarkUniformValue("uNoFadingOnSecondPass", e.noFadingOnSecondPass, (e) => !!e);
3644
3665
  }
3645
3666
  updateGraphicsData(e) {
3646
3667
  let t = e.getItemCount(), n = new bc({
@@ -3671,7 +3692,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3671
3692
  Y(t, this.programInfo, this.bufferInfo), t.drawArraysInstanced(t.TRIANGLE_STRIP, 0, n(), r);
3672
3693
  }, e);
3673
3694
  }
3674
- }, el = "flat out float vRadius;\nflat out float vRadiusWithPadding;\nflat out lowp vec4 vFillColor;\nflat out lowp vec4 vStrokeColor;\nflat out lowp float vShape;\nflat out lowp float vHalfStrokeWidth;\nflat out mat2 vRotationMatrix;\n\n// Copypaste from fragment shader\nconst float CIRCLE = 0.0;\nconst float SQUARE = 1.0;\nconst float CROSS = 2.0;\nconst float DIAMOND = 3.0;\nconst float TRIANGLE_UP = 4.0;\nconst float TRIANGLE_RIGHT = 5.0;\nconst float TRIANGLE_DOWN = 6.0;\nconst float TRIANGLE_LEFT = 7.0;\nconst float TICK_UP = 8.0;\nconst float TICK_RIGHT = 9.0;\nconst float TICK_DOWN = 10.0;\nconst float TICK_LEFT = 11.0;\nconst float X = 12.0;\nconst float PLUS = 13.0;\n\nfloat computeSemanticThresholdFactor() {\n // TODO: add smooth transition\n return getScaled_semanticScore() >= uSemanticThreshold ? 1.0 : 0.0;\n}\n\n// TODO: Move this into common.glsl or something\nvec2 getDxDy() {\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\n return vec2(getScaled_dx(), getScaled_dy()) / uViewportSize;\n#else\n return vec2(0.0, 0.0);\n#endif\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float shapeAngle = 0.0;\n\n // Selected points should always be visible\n float semanticThresholdFactor = isDatumSelected()\n ? 1.0\n : computeSemanticThresholdFactor();\n\n if (semanticThresholdFactor <= 0.0) {\n gl_PointSize = 0.0;\n // Place the vertex outside the viewport. The default (0, 0) makes this super-slow\n // on Apple Silicon. Probably related to the tile-based GPU architecture.\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n // Exit early. MAY prevent some unnecessary calculations.\n return;\n }\n\n float size = getScaled_size();\n vec2 pos = vec2(getScaled_x(), getScaled_y()) + getDxDy();\n vec2 facetedPos = applyOffset(\n applySampleFacet(pos),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n\n#ifdef VISIBLE_RANGE_CULLING\n if (isOutsideVisibleRange(facetedPos)) {\n gl_PointSize = 0.0;\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }\n#endif\n\n gl_Position = unitToNdc(facetedPos);\n\n float strokeWidth = getScaled_strokeWidth();\n float strokeOpacity = getScaled_strokeOpacity();\n vShape = getScaled_shape();\n\n // Line-only shapes use their width even when the stroke falls back to the\n // fill color. An invisible stroke must not inset other filled shapes.\n if (strokeOpacity <= 0.0 && vShape != X && vShape != PLUS) {\n strokeWidth = 0.0;\n }\n\n float diameter = sqrt(size) *\n uScaleFactor *\n semanticThresholdFactor;\n\n // Clamp minimum size and adjust opacity instead. Yields more pleasing result,\n // no flickering etc.\n float opacity = uViewOpacity;\n if (strokeWidth <= 0.0 || uInwardStroke) {\n float minDiameter = 1.0 / uDevicePixelRatio;\n if (diameter < minDiameter) {\n // We do some \"cheap\" gamma correction here. It breaks on dark background, though.\n // First we take a square of the size and then apply \"gamma\" of 1.5.\n opacity *= pow(diameter / minDiameter, 2.5);\n diameter = minDiameter;\n }\n }\n\n float fillOpa = getScaled_fillOpacity() * opacity;\n float strokeOpa = strokeOpacity * opacity;\n\n // Circle doesn't have sharp corners. Do some special optimizations to minimize the point size.\n bool circle = vShape == 0.0;\n\n if (vShape > TICK_UP && vShape <= TICK_LEFT) {\n shapeAngle = (vShape - TICK_UP) * 90.0;\n vShape = TICK_UP;\n } else if (vShape > TRIANGLE_UP && vShape <= TRIANGLE_LEFT) {\n shapeAngle = (vShape - TRIANGLE_UP) * 90.0;\n vShape = TRIANGLE_UP;\n } else if (vShape == X) {\n // The x shape reuses the perpendicular stroke geometry of plus.\n shapeAngle = -45.0;\n }\n\n float angleInDegrees = getScaled_angle();\n float angle = -(shapeAngle + angleInDegrees) * PI / 180.0;\n float sinTheta = sin(angle);\n float cosTheta = cos(angle);\n vRotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);\n\n // Not needed if we would draw rotated quads instead of gl.POINTS\n float roomForRotation = circle ? 1.0 : sin(mod(angle, PI / 2.0) + PI / 4.0) / sin(PI / 4.0);\n\n float aaPadding = 1.0 / uDevicePixelRatio;\n float rotationPadding = (diameter * roomForRotation) - diameter;\n // sqrt(3.0) ensures that the angles of equilateral triangles have enough room\n float strokePadding = uInwardStroke ? 0.0 : strokeWidth * (circle ? 1.0 : sqrt(3.0));\n float padding = rotationPadding + strokePadding + aaPadding;\n\n gl_PointSize = max(\n (diameter + padding),\n uPickingEnabled ? uMinPickingSize : 0.0\n ) * uDevicePixelRatio;\n\n vRadius = diameter / 2.0;\n vRadiusWithPadding = vRadius + padding / 2.0;\n\n vHalfStrokeWidth = strokeWidth / 2.0;\n\n vFillColor = vec4(getScaled_fill() * fillOpa, fillOpa);\n vStrokeColor = vec4(getScaled_stroke() * strokeOpa, strokeOpa);\n\n setupPicking();\n}\n", tl = "const lowp vec4 white = vec4(1.0);\nconst lowp vec4 black = vec4(0.0, 0.0, 0.0, 1.0);\n\nflat in float vRadius;\nflat in float vRadiusWithPadding;\n\nflat in lowp vec4 vFillColor;\nflat in lowp vec4 vStrokeColor;\nflat in lowp float vShape;\nflat in lowp float vHalfStrokeWidth;\n\nflat in mat2 vRotationMatrix;\n\nout lowp vec4 fragColor;\n\n// Copypaste from vertex shader\nconst float CIRCLE = 0.0;\nconst float SQUARE = 1.0;\nconst float CROSS = 2.0;\nconst float DIAMOND = 3.0;\nconst float TRIANGLE_UP = 4.0;\nconst float TICK_UP = 8.0;\nconst float X = 12.0;\nconst float PLUS = 13.0;\n\n// The distance functions are inspired by:\n// http://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm\n// However, these are not true distance functions, because the corners need to be sharp.\n\nfloat circle(vec2 p, float r) {\n return length(p) - r;\n}\n\nfloat square(vec2 p, float r) {\n p = abs(p);\n return max(p.x, p.y) - r;\n}\n\nfloat tickUp(vec2 p, float r) {\n float halfR = r * 0.5;\n p.y += halfR;\n p = abs(p);\n return max(p.x - r * 0.15, p.y - halfR);\n}\n\nfloat equilateralTriangle(vec2 p, float r) {\n p.y = -p.y;\n float k = sqrt(3.0);\n float kr = k * r;\n p.y -= kr / 2.0;\n return max((abs(p.x) * k + p.y) / 2.0, -p.y - kr);\n}\n\nfloat crossShape(vec2 p, float r, float armHalfWidth) {\n p = abs(p);\n\n vec2 b = vec2(armHalfWidth, r);\n vec2 v = abs(p) - b.xy;\n vec2 h = abs(p) - b.yx;\n return min(max(v.x, v.y), max(h.x, h.y));\n}\n\nfloat diamond(vec2 p, float r) {\n p = abs(p);\n return (max(abs(p.x - p.y), abs(p.x + p.y)) - r) / sqrt(2.0);\n}\n\nvoid main() {\n float d;\n bool lineShape = false;\n\n /** Normalized point coord */\n vec2 p = vRotationMatrix * (2.0 * gl_PointCoord - 1.0) * vRadiusWithPadding;\n float r = vRadius;\n\n // We could also use textures here. Could even be faster, because we have plenty of branching here.\n if (vShape == CIRCLE) {\n d = circle(p, r);\n\n } else if (vShape == SQUARE) {\n d = square(p, r);\n\n } else if (vShape == CROSS) {\n d = crossShape(p, r, r * 0.4);\n\n } else if (vShape == DIAMOND) {\n d = diamond(p, r);\n\n } else if (vShape == TRIANGLE_UP) {\n d = equilateralTriangle(p, r);\n\n } else if (vShape == TICK_UP) {\n d = tickUp(p, r);\n\n } else if (vShape == X || vShape == PLUS) {\n float lineLength = vShape == X ? r * sqrt(2.0) : r;\n d = crossShape(p, lineLength, vHalfStrokeWidth);\n lineShape = true;\n\n } else {\n d = 0.0;\n }\n\n if (!uPickingEnabled) {\n lowp vec4 fillColor = lineShape\n ? (vStrokeColor.a > 0.0 ? vStrokeColor : vFillColor)\n : mix(vFillColor, white, -d * uGradientStrength / vRadius);\n\n fragColor = distanceToColor(\n d + (!lineShape && uInwardStroke ? vHalfStrokeWidth : 0.0),\n fillColor,\n vStrokeColor,\n vec4(0.0),\n lineShape ? 0.0 : vHalfStrokeWidth);\n\n } else if (d - (lineShape ? 0.0 : vHalfStrokeWidth) <= 0.0) {\n fragColor = vPickingColor;\n\n } else {\n discard;\n }\n}\n", nl = "layout(std140) uniform Mark {\n /**\n * The stroke should only grow inwards, e.g, the diameter/outline is not affected by the stroke width.\n * Thus, a point that has a zero size has no visible stroke. This allows strokes to be used with\n * geometric zoom, etc.\n */\n uniform bool uInwardStroke;\n\n /** The minimum point size in pixels when rendering into the picking buffer */\n uniform float uMinPickingSize;\n\n /** Scale factor for geometric zoom */\n uniform mediump float uScaleFactor;\n\n uniform mediump float uZoomLevel;\n uniform highp float uSemanticThreshold;\n\n uniform mediump float uGradientStrength;\n\n#pragma markUniforms\n};\n", rl = class extends Pc {
3695
+ }, tl = "flat out float vRadius;\nflat out float vRadiusWithPadding;\nflat out lowp vec4 vFillColor;\nflat out lowp vec4 vStrokeColor;\nflat out lowp float vShape;\nflat out lowp float vHalfStrokeWidth;\nflat out mat2 vRotationMatrix;\n\n// Copypaste from fragment shader\nconst float CIRCLE = 0.0;\nconst float SQUARE = 1.0;\nconst float CROSS = 2.0;\nconst float DIAMOND = 3.0;\nconst float TRIANGLE_UP = 4.0;\nconst float TRIANGLE_RIGHT = 5.0;\nconst float TRIANGLE_DOWN = 6.0;\nconst float TRIANGLE_LEFT = 7.0;\nconst float TICK_UP = 8.0;\nconst float TICK_RIGHT = 9.0;\nconst float TICK_DOWN = 10.0;\nconst float TICK_LEFT = 11.0;\nconst float X = 12.0;\nconst float PLUS = 13.0;\n\nfloat computeSemanticThresholdFactor() {\n // TODO: add smooth transition\n return getScaled_semanticScore() >= uSemanticThreshold ? 1.0 : 0.0;\n}\n\n// TODO: Move this into common.glsl or something\nvec2 getDxDy() {\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\n return vec2(getScaled_dx(), getScaled_dy()) / uViewportSize;\n#else\n return vec2(0.0, 0.0);\n#endif\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float shapeAngle = 0.0;\n\n // Selected points should always be visible\n float semanticThresholdFactor = isDatumSelected()\n ? 1.0\n : computeSemanticThresholdFactor();\n\n if (semanticThresholdFactor <= 0.0) {\n gl_PointSize = 0.0;\n // Place the vertex outside the viewport. The default (0, 0) makes this super-slow\n // on Apple Silicon. Probably related to the tile-based GPU architecture.\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n // Exit early. MAY prevent some unnecessary calculations.\n return;\n }\n\n float size = getScaled_size();\n vec2 pos = vec2(getScaled_x(), getScaled_y()) + getDxDy();\n vec2 facetedPos = applyOffset(\n applySampleFacet(pos),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n\n#ifdef VISIBLE_RANGE_CULLING\n if (isOutsideVisibleRange(facetedPos)) {\n gl_PointSize = 0.0;\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }\n#endif\n\n gl_Position = unitToNdc(facetedPos);\n\n float strokeWidth = getScaled_strokeWidth();\n float strokeOpacity = getScaled_strokeOpacity();\n vShape = getScaled_shape();\n\n // Line-only shapes use their width even when the stroke falls back to the\n // fill color. An invisible stroke must not inset other filled shapes.\n if (strokeOpacity <= 0.0 && vShape != X && vShape != PLUS) {\n strokeWidth = 0.0;\n }\n\n float diameter = sqrt(size) *\n uScaleFactor *\n semanticThresholdFactor;\n\n // Clamp minimum size and adjust opacity instead. Yields more pleasing result,\n // no flickering etc.\n float opacity = uViewOpacity;\n if (strokeWidth <= 0.0 || uInwardStroke) {\n float minDiameter = 1.0 / uDevicePixelRatio;\n if (diameter < minDiameter) {\n // We do some \"cheap\" gamma correction here. It breaks on dark background, though.\n // First we take a square of the size and then apply \"gamma\" of 1.5.\n opacity *= pow(diameter / minDiameter, 2.5);\n diameter = minDiameter;\n }\n }\n\n float fillOpa = getScaled_fillOpacity() * opacity;\n float strokeOpa = strokeOpacity * opacity;\n\n // Circle doesn't have sharp corners. Do some special optimizations to minimize the point size.\n bool circle = vShape == 0.0;\n\n if (vShape > TICK_UP && vShape <= TICK_LEFT) {\n shapeAngle = (vShape - TICK_UP) * 90.0;\n vShape = TICK_UP;\n } else if (vShape > TRIANGLE_UP && vShape <= TRIANGLE_LEFT) {\n shapeAngle = (vShape - TRIANGLE_UP) * 90.0;\n vShape = TRIANGLE_UP;\n } else if (vShape == X) {\n // The x shape reuses the perpendicular stroke geometry of plus.\n shapeAngle = -45.0;\n }\n\n float angleInDegrees = getScaled_angle();\n float angle = -(shapeAngle + angleInDegrees) * PI / 180.0;\n float sinTheta = sin(angle);\n float cosTheta = cos(angle);\n vRotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);\n\n // Not needed if we would draw rotated quads instead of gl.POINTS\n float roomForRotation = circle ? 1.0 : sin(mod(angle, PI / 2.0) + PI / 4.0) / sin(PI / 4.0);\n\n float aaPadding = 1.0 / uDevicePixelRatio;\n float rotationPadding = (diameter * roomForRotation) - diameter;\n // sqrt(3.0) ensures that the angles of equilateral triangles have enough room\n float strokePadding = uInwardStroke ? 0.0 : strokeWidth * (circle ? 1.0 : sqrt(3.0));\n float padding = rotationPadding + strokePadding + aaPadding;\n\n gl_PointSize = max(\n (diameter + padding),\n uPickingEnabled ? uMinPickingSize : 0.0\n ) * uDevicePixelRatio;\n\n vRadius = diameter / 2.0;\n vRadiusWithPadding = vRadius + padding / 2.0;\n\n vHalfStrokeWidth = strokeWidth / 2.0;\n\n vFillColor = vec4(getScaled_fill() * fillOpa, fillOpa);\n vStrokeColor = vec4(getScaled_stroke() * strokeOpa, strokeOpa);\n\n setupPicking();\n}\n", nl = "const lowp vec4 white = vec4(1.0);\nconst lowp vec4 black = vec4(0.0, 0.0, 0.0, 1.0);\n\nflat in float vRadius;\nflat in float vRadiusWithPadding;\n\nflat in lowp vec4 vFillColor;\nflat in lowp vec4 vStrokeColor;\nflat in lowp float vShape;\nflat in lowp float vHalfStrokeWidth;\n\nflat in mat2 vRotationMatrix;\n\nout lowp vec4 fragColor;\n\n// Copypaste from vertex shader\nconst float CIRCLE = 0.0;\nconst float SQUARE = 1.0;\nconst float CROSS = 2.0;\nconst float DIAMOND = 3.0;\nconst float TRIANGLE_UP = 4.0;\nconst float TICK_UP = 8.0;\nconst float X = 12.0;\nconst float PLUS = 13.0;\n\n// The distance functions are inspired by:\n// http://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm\n// However, these are not true distance functions, because the corners need to be sharp.\n\nfloat circle(vec2 p, float r) {\n return length(p) - r;\n}\n\nfloat square(vec2 p, float r) {\n p = abs(p);\n return max(p.x, p.y) - r;\n}\n\nfloat tickUp(vec2 p, float r) {\n float halfR = r * 0.5;\n p.y += halfR;\n p = abs(p);\n return max(p.x - r * 0.15, p.y - halfR);\n}\n\nfloat equilateralTriangle(vec2 p, float r) {\n p.y = -p.y;\n float k = sqrt(3.0);\n float kr = k * r;\n p.y -= kr / 2.0;\n return max((abs(p.x) * k + p.y) / 2.0, -p.y - kr);\n}\n\nfloat crossShape(vec2 p, float r, float armHalfWidth) {\n p = abs(p);\n\n vec2 b = vec2(armHalfWidth, r);\n vec2 v = abs(p) - b.xy;\n vec2 h = abs(p) - b.yx;\n return min(max(v.x, v.y), max(h.x, h.y));\n}\n\nfloat diamond(vec2 p, float r) {\n p = abs(p);\n return (max(abs(p.x - p.y), abs(p.x + p.y)) - r) / sqrt(2.0);\n}\n\nvoid main() {\n float d;\n bool lineShape = false;\n\n /** Normalized point coord */\n vec2 p = vRotationMatrix * (2.0 * gl_PointCoord - 1.0) * vRadiusWithPadding;\n float r = vRadius;\n\n // We could also use textures here. Could even be faster, because we have plenty of branching here.\n if (vShape == CIRCLE) {\n d = circle(p, r);\n\n } else if (vShape == SQUARE) {\n d = square(p, r);\n\n } else if (vShape == CROSS) {\n d = crossShape(p, r, r * 0.4);\n\n } else if (vShape == DIAMOND) {\n d = diamond(p, r);\n\n } else if (vShape == TRIANGLE_UP) {\n d = equilateralTriangle(p, r);\n\n } else if (vShape == TICK_UP) {\n d = tickUp(p, r);\n\n } else if (vShape == X || vShape == PLUS) {\n float lineLength = vShape == X ? r * sqrt(2.0) : r;\n d = crossShape(p, lineLength, vHalfStrokeWidth);\n lineShape = true;\n\n } else {\n d = 0.0;\n }\n\n if (!uPickingEnabled) {\n lowp vec4 fillColor = lineShape\n ? (vStrokeColor.a > 0.0 ? vStrokeColor : vFillColor)\n : mix(vFillColor, white, -d * uGradientStrength / vRadius);\n\n fragColor = distanceToColor(\n d + (!lineShape && uInwardStroke ? vHalfStrokeWidth : 0.0),\n fillColor,\n vStrokeColor,\n vec4(0.0),\n lineShape ? 0.0 : vHalfStrokeWidth);\n\n } else if (d - (lineShape ? 0.0 : vHalfStrokeWidth) <= 0.0) {\n fragColor = vPickingColor;\n\n } else {\n discard;\n }\n}\n", rl = "layout(std140) uniform Mark {\n /**\n * The stroke should only grow inwards, e.g, the diameter/outline is not affected by the stroke width.\n * Thus, a point that has a zero size has no visible stroke. This allows strokes to be used with\n * geometric zoom, etc.\n */\n uniform bool uInwardStroke;\n\n /** The minimum point size in pixels when rendering into the picking buffer */\n uniform float uMinPickingSize;\n\n /** Scale factor for geometric zoom */\n uniform mediump float uScaleFactor;\n\n uniform mediump float uZoomLevel;\n uniform highp float uSemanticThreshold;\n\n uniform mediump float uGradientStrength;\n\n#pragma markUniforms\n};\n", il = class extends Fc {
3675
3696
  getAttributes() {
3676
3697
  return [
3677
3698
  "uniqueId",
@@ -3694,7 +3715,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3694
3715
  ];
3695
3716
  }
3696
3717
  initializeGraphics() {
3697
- super.initializeGraphics(), this.createAndLinkShaders(el, tl, [nl]);
3718
+ super.initializeGraphics(), this.createAndLinkShaders(tl, nl, [rl]);
3698
3719
  }
3699
3720
  finalizeGraphicsInitialization() {
3700
3721
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
@@ -3730,7 +3751,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3730
3751
  n && so(t, this.vertexArrayInfo, t.POINTS, n, e);
3731
3752
  }, e);
3732
3753
  }
3733
- }, il = "flat out lowp vec4 vFillColor;\nflat out lowp vec4 vStrokeColor;\nflat out float vHalfStrokeWidth;\nflat out vec4 vCornerRadii;\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n/** Position for SDF-strokes */\nout vec2 vPosInPixels;\n#endif\n\n/** Size of the rect in pixels */\nflat out vec2 vHalfSizeInPixels;\n\n/**\n * Adjusts the vertex position to ensure that the rectangle is at least `minSpan`\n * wide or high. Returns a value that reflects the amount of clamping and can be\n * used to adjust the opacity of the rectangle.\n *\n * pos: vertex position\n * frac: vertex position within the rectangle, [0, 1]\n * size: width or height of the rectangle\n * minSize: minimum width or height of the rectangle\n */\nfloat clampMinSize(inout float pos, float frac, float size, float minSize) {\n if (minSize > 0.0 && size < minSize) {\n pos += (frac - 0.5) * (minSize - size);\n return size / minSize;\n }\n\n return 1.0;\n}\n\nvoid sort(inout float a, inout float b) {\n if (a > b) {\n float tmp = b;\n b = a;\n a = tmp;\n }\n}\n\n/**\n * The vertex position wrt the rectangle specified by (x, x2, y, y2).\n * [0, 0] = [x, y], [1, 1] = [x2, y2]. \n * The x or y component may contain fractional values if the rectangle \n * have been tessellated.\n */\nvec2 getVertexPos() {\n int index = gl_VertexID % 6;\n return vec2(\n index == 0 || index == 1 || index == 3 ? 0.0 : 1.0,\n index == 0 || index == 1 || index == 2 ? 0.0 : 1.0\n );\n \n}\n\nvoid main(void) {\n#pragma orderGuard\n\n vec2 frac = getVertexPos();\n\n vec2 normalizedMinSize = vec2(uMinWidth, uMinHeight) / uViewportSize;\n vec4 cornerRadii = vec4(\n uCornerRadiusTopRight,\n uCornerRadiusBottomRight,\n uCornerRadiusTopLeft,\n uCornerRadiusBottomLeft\n );\n\n SampleFacetPosition sampleFacetPos = getSampleFacetPos();\n if (sampleFacetPos.height == 0.0) {\n // Filtered samples have no facet height. Cull them before minimum-size\n // clamping can expand their rectangles at the viewport boundary.\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }\n\n vec2 pos1 = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n vec2 pos2 = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n );\n\n sort(pos1.x, pos2.x);\n sort(pos1.y, pos2.y);\n\n // Clamp x to prevent precision artifacts when the scale is zoomed very close.\n // TODO: clamp y as well\n float clampMargin = 1.0;\n pos1.x = clamp(pos1.x, 0.0 - clampMargin, 1.0 + clampMargin);\n pos2.x = clamp(pos2.x, 0.0 - clampMargin, 1.0 + clampMargin);\n\n vec2 size = pos2 - pos1;\n\n if (size.x < 0.0 || size.y < 0.0) {\n // Keep zero-sized rects alive so min-size clamping can stabilize them.\n gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n\n vec2 pos = pos1 + frac * size;\n\n // Clamp to minimum size, optionally compensate with opacity\n float opaFactor = uViewOpacity * max(uMinOpacity,\n clampMinSize(pos.x, frac.x, size.x, normalizedMinSize.x) *\n clampMinSize(pos.y, frac.y, size.y, normalizedMinSize.y));\n\n size = max(size, normalizedMinSize);\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n // Add an extra pixel to the stroke width to accommodate edge antialiasing\n float aaPadding = 1.0 / uDevicePixelRatio;\n\n // TODO: Only expand to the offset direction. Now high offsets result in\n // a large expansion in all directions.\n float shadowPadding = uShadowBlur + max(abs(uShadowOffsetX), abs(uShadowOffsetY));\n\n float strokeWidth = getScaled_strokeWidth();\n float strokeOpacity = getScaled_strokeOpacity() * opaFactor;\n\n vec2 centeredFrac = frac - 0.5;\n vec2 expand = centeredFrac * (strokeWidth + aaPadding + shadowPadding * 2.0) / uViewportSize;\n pos += expand;\n\n vec2 sizeInPixels = size * uViewportSize;\n vPosInPixels = (centeredFrac + expand / size) * sizeInPixels;\n\n vHalfSizeInPixels = sizeInPixels / 2.0;\n\n vCornerRadii = min(cornerRadii, min(vHalfSizeInPixels.x, vHalfSizeInPixels.y));\n vHalfStrokeWidth = strokeWidth / 2.0;\n vStrokeColor = vec4(getScaled_stroke() * strokeOpacity, strokeOpacity);\n#endif\n\n gl_Position = unitToNdc(pos);\n\n float fillOpacity = getScaled_fillOpacity() * opaFactor;\n vFillColor = vec4(getScaled_fill() * fillOpacity, fillOpacity);\n\n setupPicking();\n}\n", al = "#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nin vec2 vPosInPixels;\n#endif\n\nflat in vec2 vHalfSizeInPixels;\n\nflat in lowp vec4 vFillColor;\nflat in lowp vec4 vStrokeColor;\nflat in float vHalfStrokeWidth;\nflat in vec4 vCornerRadii;\n\nout lowp vec4 fragColor;\n\n// ----------------------------------------------------------------------------\n// Shadow source: https://madebyevan.com/shaders/fast-rounded-rectangle-shadows/\n// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)\n\n#ifdef SHADOW\n\n// A standard gaussian function, used for weighting samples\nfloat gaussian(float x, float sigma) {\n const float pi = 3.141592653589793;\n return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(2.0 * pi) * sigma);\n}\n\n// This approximates the error function, needed for the gaussian integral\nvec2 erf(vec2 x) {\n vec2 s = sign(x), a = abs(x);\n x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;\n x *= x;\n return s - s / (x * x);\n}\n\n// Return the blurred mask along the x dimension\nfloat roundedBoxShadowX(float x, float y, float sigma, float corner, vec2 halfSize) {\n float delta = min(halfSize.y - corner - abs(y), 0.0);\n float curved = halfSize.x - corner + sqrt(max(0.0, corner * corner - delta * delta));\n vec2 integral = 0.5 + 0.5 * erf((x + vec2(-curved, curved)) * (sqrt(0.5) / sigma));\n return integral.y - integral.x;\n}\n\n// Return the mask for the shadow of a box from lower to upper\nfloat roundedBoxShadow(vec2 lower, vec2 upper, vec2 point, float sigma, float corner) {\n // Center everything to make the math easier\n vec2 center = (lower + upper) * 0.5;\n vec2 halfSize = (upper - lower) * 0.5;\n point -= center;\n\n // The signal is only non-zero in a limited range, so don't waste samples\n float low = point.y - halfSize.y;\n float high = point.y + halfSize.y;\n float start = clamp(-3.0 * sigma, low, high);\n float end = clamp(3.0 * sigma, low, high);\n\n // Accumulate samples (we can get away with surprisingly few samples)\n float step = (end - start) / 4.0;\n float y = start + step * 0.5;\n float value = 0.0;\n for (int i = 0; i < 4; i++) {\n value += roundedBoxShadowX(point.x, point.y - y, sigma, corner, halfSize) * gaussian(y, sigma) * step;\n y += step;\n }\n\n return value;\n}\n\n// ----------------------------------------------------------------------------\n\n#endif\n\n// Source: https://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm\nfloat sdRoundedBox(vec2 p, vec2 b, vec4 r) {\n r.xy = p.x > 0.0 ? r.xy : r.zw;\n r.x = p.y > 0.0 ? r.x : r.y;\n vec2 q = abs(p) - b + r.x;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;\n}\n\n// Not a true SDF. Makes the corners of strokes sharp and is faster.\nfloat sdSharpBox(vec2 p, vec2 b) {\n vec2 q = abs(p) - b;\n return max(q.x, q.y);\n}\n\nfloat diagonalPattern(vec2 uv, float spacing) {\n // Using 1.5 to approximate sqrt(2.0) to reduce aliasing artifacts.\n float divisor = spacing * vHalfStrokeWidth * 2.0 * 1.5;\n return abs(mod(uv.x - uv.y, divisor) - 0.5 * divisor) / 1.5;\n}\n\nfloat verticalPattern(float x, float spacing) {\n float divisor = spacing * vHalfStrokeWidth * 2.0;\n return abs(mod(x, divisor)) / 2.0;\n}\n\nfloat circle(vec2 p, float r) {\n return length(p) - r;\n}\n\nfloat masonryCirclePattern(vec2 uv, float spacing, float radius) {\n float halfSpacing = 0.5 * spacing;\n\n float row = floor(uv.y / spacing);\n float shift = mod(row, 2.0) * halfSpacing;\n\n vec2 shifted = vec2(uv.x + shift, uv.y + halfSpacing);\n vec2 cell = mod(shifted + 0.5 * spacing, spacing) - halfSpacing;\n\n return abs(circle(cell, radius));\n}\n\n/**\n * Patterns:\n * 0 none\n * 1 diagonal (/)\n * 2 antiDiagonal (\\)\n * 3 cross (X)\n * 4 vertical (|)\n * 5 horizontal (-)\n * 6 grid (+)\n * 7 dots (.)\n * 8 rings (o)\n * 9 ringsLarge (O)\n */\nfloat pattern() {\n#ifdef STROKED\n int patternType = uHatchPattern;\n vec2 uv = vPosInPixels;\n float spacing = 4.0;\n\n switch (patternType) {\n case 1:\n return diagonalPattern(vec2(uv.x, -uv.y), spacing);\n case 2:\n return diagonalPattern(uv, spacing);\n case 3:\n return min(\n diagonalPattern(uv, spacing),\n diagonalPattern(vec2(uv.x, -uv.y), spacing)\n );\n case 4:\n return verticalPattern(uv.x, spacing);\n case 5:\n return verticalPattern(uv.y, spacing);\n case 6:\n return min(\n verticalPattern(uv.x, spacing),\n verticalPattern(uv.y, spacing)\n );\n case 7:\n case 8:\n case 9: {\n float spacing = vHalfStrokeWidth * 14.0;\n float radius = spacing * (\n patternType == 8 ? 0.2 :\n patternType == 9 ? 0.35 :\n 0.07\n );\n return masonryCirclePattern(uv, spacing, radius);\n }\n default:\n break;\n }\n#endif\n return 1.0 / 0.0; // Infinity\n}\n\nvoid main(void) {\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n#ifdef ROUNDED_CORNERS\n // Distance from rectangle's edge in pixels. Negative inside the rectangle.\n float d = sdRoundedBox(vPosInPixels, vHalfSizeInPixels, vCornerRadii);\n#else\n float d = sdSharpBox(vPosInPixels, vHalfSizeInPixels);\n#endif\n\n vec4 backgroundColor = vec4(0.0, 0.0, 0.0, 0.0);\n\n#ifdef SHADOW\n float maxCornerRadius = max(vCornerRadii.x, max(vCornerRadii.y, max(vCornerRadii.z, vCornerRadii.w)));\n\n float shadow = 0.0;\n // Only calculate shadow for the region outside the stroke.\n if (d >= vHalfStrokeWidth - 1.0 && uShadowOpacity > 0.0) {\n shadow = roundedBoxShadow(\n -vHalfSizeInPixels - vHalfStrokeWidth,\n vHalfSizeInPixels + vHalfStrokeWidth,\n vPosInPixels - vec2(uShadowOffsetX, -uShadowOffsetY),\n max(uShadowBlur / 2.5, 0.25),\n maxCornerRadius + vHalfStrokeWidth\n ) * uShadowOpacity * uViewOpacity;\n }\n backgroundColor = vec4(uShadowColor * shadow, shadow);\n#endif\n\n if (vHalfStrokeWidth > 0.0 && uHatchPattern > 0) {\n d = max(d, -pattern());\n }\n\n fragColor = distanceToColor(\n d,\n vFillColor,\n vStrokeColor,\n backgroundColor,\n vHalfStrokeWidth\n );\n\n if (uPickingEnabled) {\n if (d < vHalfStrokeWidth) {\n fragColor = vPickingColor;\n }\n } else if (fragColor.a == 0.0) {\n discard;\n }\n#else\n // The trivial, non-decorated case\n fragColor = vFillColor;\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n#endif\n}\n", ol = "layout(std140) uniform Mark {\n /** Minimum size (width, height) of the displayed rectangle in pixels */\n uniform float uMinWidth;\n uniform float uMinHeight;\n\n /** Minimum opacity for the size clamping */\n uniform float uMinOpacity;\n\n uniform float uCornerRadiusTopRight;\n uniform float uCornerRadiusBottomRight;\n uniform float uCornerRadiusTopLeft;\n uniform float uCornerRadiusBottomLeft;\n\n uniform int uHatchPattern;\n\n uniform vec3 uShadowColor;\n uniform float uShadowOpacity;\n uniform float uShadowBlur;\n uniform float uShadowOffsetX;\n uniform float uShadowOffsetY;\n\n#pragma markUniforms\n};\n", sl = [
3754
+ }, al = "flat out lowp vec4 vFillColor;\nflat out lowp vec4 vStrokeColor;\nflat out float vHalfStrokeWidth;\nflat out vec4 vCornerRadii;\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n/** Position for SDF-strokes */\nout vec2 vPosInPixels;\n#endif\n\n/** Size of the rect in pixels */\nflat out vec2 vHalfSizeInPixels;\n\n/**\n * Adjusts the vertex position to ensure that the rectangle is at least `minSpan`\n * wide or high. Returns a value that reflects the amount of clamping and can be\n * used to adjust the opacity of the rectangle.\n *\n * pos: vertex position\n * frac: vertex position within the rectangle, [0, 1]\n * size: width or height of the rectangle\n * minSize: minimum width or height of the rectangle\n */\nfloat clampMinSize(inout float pos, float frac, float size, float minSize) {\n if (minSize > 0.0 && size < minSize) {\n pos += (frac - 0.5) * (minSize - size);\n return size / minSize;\n }\n\n return 1.0;\n}\n\nvoid sort(inout float a, inout float b) {\n if (a > b) {\n float tmp = b;\n b = a;\n a = tmp;\n }\n}\n\n/**\n * The vertex position wrt the rectangle specified by (x, x2, y, y2).\n * [0, 0] = [x, y], [1, 1] = [x2, y2]. \n * The x or y component may contain fractional values if the rectangle \n * have been tessellated.\n */\nvec2 getVertexPos() {\n int index = gl_VertexID % 6;\n return vec2(\n index == 0 || index == 1 || index == 3 ? 0.0 : 1.0,\n index == 0 || index == 1 || index == 2 ? 0.0 : 1.0\n );\n \n}\n\nvoid main(void) {\n#pragma orderGuard\n\n vec2 frac = getVertexPos();\n\n vec2 normalizedMinSize = vec2(uMinWidth, uMinHeight) / uViewportSize;\n vec4 cornerRadii = vec4(\n uCornerRadiusTopRight,\n uCornerRadiusBottomRight,\n uCornerRadiusTopLeft,\n uCornerRadiusBottomLeft\n );\n\n SampleFacetPosition sampleFacetPos = getSampleFacetPos();\n if (sampleFacetPos.height == 0.0) {\n // Filtered samples have no facet height. Cull them before minimum-size\n // clamping can expand their rectangles at the viewport boundary.\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }\n\n vec2 pos1 = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n vec2 pos2 = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n );\n\n sort(pos1.x, pos2.x);\n sort(pos1.y, pos2.y);\n\n // Clamp x to prevent precision artifacts when the scale is zoomed very close.\n // TODO: clamp y as well\n float clampMargin = 1.0;\n pos1.x = clamp(pos1.x, 0.0 - clampMargin, 1.0 + clampMargin);\n pos2.x = clamp(pos2.x, 0.0 - clampMargin, 1.0 + clampMargin);\n\n vec2 size = pos2 - pos1;\n\n if (size.x < 0.0 || size.y < 0.0) {\n // Keep zero-sized rects alive so min-size clamping can stabilize them.\n gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n\n vec2 pos = pos1 + frac * size;\n\n // Clamp to minimum size, optionally compensate with opacity\n float opaFactor = uViewOpacity * max(uMinOpacity,\n clampMinSize(pos.x, frac.x, size.x, normalizedMinSize.x) *\n clampMinSize(pos.y, frac.y, size.y, normalizedMinSize.y));\n\n size = max(size, normalizedMinSize);\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n // Add an extra pixel to the stroke width to accommodate edge antialiasing\n float aaPadding = 1.0 / uDevicePixelRatio;\n\n // TODO: Only expand to the offset direction. Now high offsets result in\n // a large expansion in all directions.\n float shadowPadding = uShadowBlur + max(abs(uShadowOffsetX), abs(uShadowOffsetY));\n\n float strokeWidth = getScaled_strokeWidth();\n float strokeOpacity = getScaled_strokeOpacity() * opaFactor;\n\n vec2 centeredFrac = frac - 0.5;\n vec2 expand = centeredFrac * (strokeWidth + aaPadding + shadowPadding * 2.0) / uViewportSize;\n pos += expand;\n\n vec2 sizeInPixels = size * uViewportSize;\n vPosInPixels = (centeredFrac + expand / size) * sizeInPixels;\n\n vHalfSizeInPixels = sizeInPixels / 2.0;\n\n vCornerRadii = min(cornerRadii, min(vHalfSizeInPixels.x, vHalfSizeInPixels.y));\n vHalfStrokeWidth = strokeWidth / 2.0;\n vStrokeColor = vec4(getScaled_stroke() * strokeOpacity, strokeOpacity);\n#endif\n\n gl_Position = unitToNdc(pos);\n\n float fillOpacity = getScaled_fillOpacity() * opaFactor;\n vFillColor = vec4(getScaled_fill() * fillOpacity, fillOpacity);\n\n setupPicking();\n}\n", ol = "#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nin vec2 vPosInPixels;\n#endif\n\nflat in vec2 vHalfSizeInPixels;\n\nflat in lowp vec4 vFillColor;\nflat in lowp vec4 vStrokeColor;\nflat in float vHalfStrokeWidth;\nflat in vec4 vCornerRadii;\n\nout lowp vec4 fragColor;\n\n// ----------------------------------------------------------------------------\n// Shadow source: https://madebyevan.com/shaders/fast-rounded-rectangle-shadows/\n// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)\n\n#ifdef SHADOW\n\n// A standard gaussian function, used for weighting samples\nfloat gaussian(float x, float sigma) {\n const float pi = 3.141592653589793;\n return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(2.0 * pi) * sigma);\n}\n\n// This approximates the error function, needed for the gaussian integral\nvec2 erf(vec2 x) {\n vec2 s = sign(x), a = abs(x);\n x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;\n x *= x;\n return s - s / (x * x);\n}\n\n// Return the blurred mask along the x dimension\nfloat roundedBoxShadowX(float x, float y, float sigma, float corner, vec2 halfSize) {\n float delta = min(halfSize.y - corner - abs(y), 0.0);\n float curved = halfSize.x - corner + sqrt(max(0.0, corner * corner - delta * delta));\n vec2 integral = 0.5 + 0.5 * erf((x + vec2(-curved, curved)) * (sqrt(0.5) / sigma));\n return integral.y - integral.x;\n}\n\n// Return the mask for the shadow of a box from lower to upper\nfloat roundedBoxShadow(vec2 lower, vec2 upper, vec2 point, float sigma, float corner) {\n // Center everything to make the math easier\n vec2 center = (lower + upper) * 0.5;\n vec2 halfSize = (upper - lower) * 0.5;\n point -= center;\n\n // The signal is only non-zero in a limited range, so don't waste samples\n float low = point.y - halfSize.y;\n float high = point.y + halfSize.y;\n float start = clamp(-3.0 * sigma, low, high);\n float end = clamp(3.0 * sigma, low, high);\n\n // Accumulate samples (we can get away with surprisingly few samples)\n float step = (end - start) / 4.0;\n float y = start + step * 0.5;\n float value = 0.0;\n for (int i = 0; i < 4; i++) {\n value += roundedBoxShadowX(point.x, point.y - y, sigma, corner, halfSize) * gaussian(y, sigma) * step;\n y += step;\n }\n\n return value;\n}\n\n// ----------------------------------------------------------------------------\n\n#endif\n\n// Source: https://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm\nfloat sdRoundedBox(vec2 p, vec2 b, vec4 r) {\n r.xy = p.x > 0.0 ? r.xy : r.zw;\n r.x = p.y > 0.0 ? r.x : r.y;\n vec2 q = abs(p) - b + r.x;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;\n}\n\n// Not a true SDF. Makes the corners of strokes sharp and is faster.\nfloat sdSharpBox(vec2 p, vec2 b) {\n vec2 q = abs(p) - b;\n return max(q.x, q.y);\n}\n\nfloat diagonalPattern(vec2 uv, float spacing) {\n // Using 1.5 to approximate sqrt(2.0) to reduce aliasing artifacts.\n float divisor = spacing * vHalfStrokeWidth * 2.0 * 1.5;\n return abs(mod(uv.x - uv.y, divisor) - 0.5 * divisor) / 1.5;\n}\n\nfloat verticalPattern(float x, float spacing) {\n float divisor = spacing * vHalfStrokeWidth * 2.0;\n return abs(mod(x, divisor)) / 2.0;\n}\n\nfloat circle(vec2 p, float r) {\n return length(p) - r;\n}\n\nfloat masonryCirclePattern(vec2 uv, float spacing, float radius) {\n float halfSpacing = 0.5 * spacing;\n\n float row = floor(uv.y / spacing);\n float shift = mod(row, 2.0) * halfSpacing;\n\n vec2 shifted = vec2(uv.x + shift, uv.y + halfSpacing);\n vec2 cell = mod(shifted + 0.5 * spacing, spacing) - halfSpacing;\n\n return abs(circle(cell, radius));\n}\n\n/**\n * Patterns:\n * 0 none\n * 1 diagonal (/)\n * 2 antiDiagonal (\\)\n * 3 cross (X)\n * 4 vertical (|)\n * 5 horizontal (-)\n * 6 grid (+)\n * 7 dots (.)\n * 8 rings (o)\n * 9 ringsLarge (O)\n */\nfloat pattern() {\n#ifdef STROKED\n int patternType = uHatchPattern;\n vec2 uv = vPosInPixels;\n float spacing = 4.0;\n\n switch (patternType) {\n case 1:\n return diagonalPattern(vec2(uv.x, -uv.y), spacing);\n case 2:\n return diagonalPattern(uv, spacing);\n case 3:\n return min(\n diagonalPattern(uv, spacing),\n diagonalPattern(vec2(uv.x, -uv.y), spacing)\n );\n case 4:\n return verticalPattern(uv.x, spacing);\n case 5:\n return verticalPattern(uv.y, spacing);\n case 6:\n return min(\n verticalPattern(uv.x, spacing),\n verticalPattern(uv.y, spacing)\n );\n case 7:\n case 8:\n case 9: {\n float spacing = vHalfStrokeWidth * 14.0;\n float radius = spacing * (\n patternType == 8 ? 0.2 :\n patternType == 9 ? 0.35 :\n 0.07\n );\n return masonryCirclePattern(uv, spacing, radius);\n }\n default:\n break;\n }\n#endif\n return 1.0 / 0.0; // Infinity\n}\n\nvoid main(void) {\n\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n#ifdef ROUNDED_CORNERS\n // Distance from rectangle's edge in pixels. Negative inside the rectangle.\n float d = sdRoundedBox(vPosInPixels, vHalfSizeInPixels, vCornerRadii);\n#else\n float d = sdSharpBox(vPosInPixels, vHalfSizeInPixels);\n#endif\n\n vec4 backgroundColor = vec4(0.0, 0.0, 0.0, 0.0);\n\n#ifdef SHADOW\n float maxCornerRadius = max(vCornerRadii.x, max(vCornerRadii.y, max(vCornerRadii.z, vCornerRadii.w)));\n\n float shadow = 0.0;\n // Only calculate shadow for the region outside the stroke.\n if (d >= vHalfStrokeWidth - 1.0 && uShadowOpacity > 0.0) {\n shadow = roundedBoxShadow(\n -vHalfSizeInPixels - vHalfStrokeWidth,\n vHalfSizeInPixels + vHalfStrokeWidth,\n vPosInPixels - vec2(uShadowOffsetX, -uShadowOffsetY),\n max(uShadowBlur / 2.5, 0.25),\n maxCornerRadius + vHalfStrokeWidth\n ) * uShadowOpacity * uViewOpacity;\n }\n backgroundColor = vec4(uShadowColor * shadow, shadow);\n#endif\n\n if (vHalfStrokeWidth > 0.0 && uHatchPattern > 0) {\n d = max(d, -pattern());\n }\n\n fragColor = distanceToColor(\n d,\n vFillColor,\n vStrokeColor,\n backgroundColor,\n vHalfStrokeWidth\n );\n\n if (uPickingEnabled) {\n if (d < vHalfStrokeWidth) {\n fragColor = vPickingColor;\n }\n } else if (fragColor.a == 0.0) {\n discard;\n }\n#else\n // The trivial, non-decorated case\n fragColor = vFillColor;\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n#endif\n}\n", sl = "layout(std140) uniform Mark {\n /** Minimum size (width, height) of the displayed rectangle in pixels */\n uniform float uMinWidth;\n uniform float uMinHeight;\n\n /** Minimum opacity for the size clamping */\n uniform float uMinOpacity;\n\n uniform float uCornerRadiusTopRight;\n uniform float uCornerRadiusBottomRight;\n uniform float uCornerRadiusTopLeft;\n uniform float uCornerRadiusBottomLeft;\n\n uniform int uHatchPattern;\n\n uniform vec3 uShadowColor;\n uniform float uShadowOpacity;\n uniform float uShadowBlur;\n uniform float uShadowOffsetX;\n uniform float uShadowOffsetY;\n\n#pragma markUniforms\n};\n", cl = [
3734
3755
  "none",
3735
3756
  "diagonal",
3736
3757
  "antiDiagonal",
@@ -3741,7 +3762,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3741
3762
  "dots",
3742
3763
  "rings",
3743
3764
  "ringsLarge"
3744
- ], cl = class extends Pc {
3765
+ ], ll = class extends Fc {
3745
3766
  get opaque() {
3746
3767
  return ye(this, "opaque", () => !this.#e() && !this.#t() && !this.properties.shadowOpacity && c(this.encoding.fillOpacity) && this.encoding.fillOpacity.value == 1 && this.properties.minOpacity == 1) && this.unitView.getEffectiveOpacity() == 1;
3747
3768
  }
@@ -3775,12 +3796,12 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3775
3796
  initializeGraphics() {
3776
3797
  super.initializeGraphics();
3777
3798
  let e = [];
3778
- this.#e() && e.push("ROUNDED_CORNERS"), this.#t() && e.push("STROKED"), this.properties.shadowOpacity && e.push("SHADOW"), this.createAndLinkShaders(il, al, [ol, ...e.map((e) => "#define " + e)]);
3799
+ this.#e() && e.push("ROUNDED_CORNERS"), this.#t() && e.push("STROKED"), this.properties.shadowOpacity && e.push("SHADOW"), this.createAndLinkShaders(al, ol, [sl, ...e.map((e) => "#define " + e)]);
3779
3800
  }
3780
3801
  finalizeGraphicsInitialization() {
3781
3802
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
3782
3803
  let e = this.properties;
3783
- this.registerMarkUniformValue("uMinWidth", e.minWidth), this.registerMarkUniformValue("uMinHeight", e.minHeight), this.registerMarkUniformValue("uMinOpacity", e.minOpacity), this.registerMarkUniformValue("uCornerRadiusTopRight", e.cornerRadiusTopRight ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusBottomRight", e.cornerRadiusBottomRight ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusTopLeft", e.cornerRadiusTopLeft ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusBottomLeft", e.cornerRadiusBottomLeft ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uHatchPattern", e.hatch, (e) => Math.max(0, sl.indexOf(e ?? "none"))), this.registerMarkUniformValue("uShadowBlur", e.shadowBlur ?? 0), this.registerMarkUniformValue("uShadowOpacity", e.shadowOpacity ?? 0), this.registerMarkUniformValue("uShadowOffsetX", e.shadowOffsetX ?? 0), this.registerMarkUniformValue("uShadowOffsetY", e.shadowOffsetY ?? 0), this.registerMarkUniformValue("uShadowColor", e.shadowColor ?? "black", Zo);
3804
+ this.registerMarkUniformValue("uMinWidth", e.minWidth), this.registerMarkUniformValue("uMinHeight", e.minHeight), this.registerMarkUniformValue("uMinOpacity", e.minOpacity), this.registerMarkUniformValue("uCornerRadiusTopRight", e.cornerRadiusTopRight ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusBottomRight", e.cornerRadiusBottomRight ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusTopLeft", e.cornerRadiusTopLeft ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uCornerRadiusBottomLeft", e.cornerRadiusBottomLeft ?? e.cornerRadius ?? 0), this.registerMarkUniformValue("uHatchPattern", e.hatch, (e) => Math.max(0, cl.indexOf(e ?? "none"))), this.registerMarkUniformValue("uShadowBlur", e.shadowBlur ?? 0), this.registerMarkUniformValue("uShadowOpacity", e.shadowOpacity ?? 0), this.registerMarkUniformValue("uShadowOffsetX", e.shadowOffsetX ?? 0), this.registerMarkUniformValue("uShadowOffsetY", e.shadowOffsetY ?? 0), this.registerMarkUniformValue("uShadowColor", e.shadowColor ?? "black", Zo);
3784
3805
  }
3785
3806
  updateGraphicsData(e) {
3786
3807
  let t = e.getItemCount(), n = new _c({
@@ -3802,7 +3823,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3802
3823
  so(t, this.vertexArrayInfo, t.TRIANGLE_STRIP, n, e);
3803
3824
  }, e);
3804
3825
  }
3805
- }, ll = "// Line caps\nconst int BUTT = 0;\nconst int SQUARE = 1;\nconst int ROUND = 2;\n\n/** Position along the rule */\nin float pos;\n\n/** Which side of the stroke: -0.5 or 0.5 */\nin float side;\n\nflat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\n/** The distance from the line center to the direction of normal in pixels */\nout float vNormalLengthInPixels;\n\n/** Distances from the line endings. Used for rendering the round caps and dashes */\nout highp vec2 vPosInPixels;\n\n\nvoid main(void) {\n#pragma orderGuard\n\n float pixelSize = 1.0 / uDevicePixelRatio;\n\n // Stroke width in pixels\n float size = getScaled_size();\n float opacity = getScaled_opacity() * uViewOpacity;\n\n // Avoid artifacts in very thin lines by clamping the size and adjusting opacity respectively\n if (size < pixelSize) {\n opacity *= size / pixelSize;\n size = pixelSize;\n }\n\n vec2 a = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n vec2 b = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n );\n\n vec2 tangent = b - a;\n\n float offset = 0.0;\n float relativeDiff = 0.0;\n if (uMinLength > 0.0 || uStrokeCap != BUTT) {\n float len = length(tangent * uViewportSize);\n\n // Elongate to reach the minimum length.\n // The length difference in pixels\n float diff = max(0.0, uMinLength - len);\n\n // Add line caps\n if (uStrokeCap != BUTT) {\n diff += size;\n }\n\n relativeDiff = diff / len;\n offset = relativeDiff * (pos - 0.5);\n }\n\n // Apply caps and minimum length by spreading the vertices along the tangent\n vec2 p = pos < 1.0\n ? a + tangent * (pos + offset)\n : b + tangent * offset;\n\n // Add an extra pixel to stroke width to accommodate edge antialiasing\n float aaPadding = pixelSize;\n\n // Extrude\n vec2 normal = normalize(vec2(-tangent.y, tangent.x) / uViewportSize);\n p += normal * side * (size + aaPadding) / uViewportSize;\n\n gl_Position = unitToNdc(p);\n\n vColor = vec4(getScaled_color() * opacity, opacity);\n vSize = size;\n vNormalLengthInPixels = side * (size + aaPadding);\n\n // TODO: Here's a precision problem that breaks round caps when zoomed in enough\n vPosInPixels = vec2(pos, (1.0 - pos)) * (1.0 + relativeDiff) * length(tangent * uViewportSize) -\n vec2(uStrokeCap != BUTT ? size / 2.0 : 0.0);\n \n setupPicking();\n}\n", ul = "// Line ending\nconst int BUTT = 0;\nconst int SQUARE = 1;\nconst int ROUND = 2;\n\nuniform sampler2D uDashTexture;\n\nflat in vec4 vColor;\nflat in float vSize;\n\n/** Position on the rule along its length in pixels */\nin vec2 vPosInPixels;\nin float vNormalLengthInPixels;\n\nout lowp vec4 fragColor;\n\nvoid main(void) {\n float dpr = uDevicePixelRatio;\n\n float distanceFromEnd = -min(vPosInPixels[0], vPosInPixels[1]);\n float distance; // from the rule centerline or end\n if (distanceFromEnd > 0.0 && uStrokeCap == ROUND) {\n // round cap\n distance = length(vec2(distanceFromEnd, vNormalLengthInPixels));\n } else {\n distance = abs(vNormalLengthInPixels);\n }\n\n // Use a signed distance field to implement edge antialiasing\n float opacity = clamp(((vSize / 2.0 - distance) * dpr), -0.5, 0.5) + 0.5;\n\n if (uDashTextureSize > 0.0) {\n float pos = (vPosInPixels[0] + uStrokeDashOffset) * dpr;\n float floored = floor(pos);\n vec2 texelPositions = (floored + vec2(0.5, 1.5)) / dpr / uDashTextureSize;\n \n // Do antialiasing\n opacity *= mix(\n texture(uDashTexture, vec2(texelPositions[0], 0)).r,\n texture(uDashTexture, vec2(texelPositions[1], 0)).r,\n clamp((pos - floored), 0.0, 1.0));\n }\n\n fragColor = vColor * opacity;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", dl = "layout(std140) uniform Mark {\n /** Minimum rule length in pixels */\n uniform mediump float uMinLength;\n\n uniform mediump float uDashTextureSize;\n uniform lowp int uStrokeCap;\n uniform mediump float uStrokeDashOffset;\n\n#pragma markUniforms\n};\n", fl = class extends Pc {
3826
+ }, ul = "// Line caps\nconst int BUTT = 0;\nconst int SQUARE = 1;\nconst int ROUND = 2;\n\n/** Position along the rule */\nin float pos;\n\n/** Which side of the stroke: -0.5 or 0.5 */\nin float side;\n\nflat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\n/** The distance from the line center to the direction of normal in pixels */\nout float vNormalLengthInPixels;\n\n/** Distances from the line endings. Used for rendering the round caps and dashes */\nout highp vec2 vPosInPixels;\n\n\nvoid main(void) {\n#pragma orderGuard\n\n float pixelSize = 1.0 / uDevicePixelRatio;\n\n // Stroke width in pixels\n float size = getScaled_size();\n float opacity = getScaled_opacity() * uViewOpacity;\n\n // Avoid artifacts in very thin lines by clamping the size and adjusting opacity respectively\n if (size < pixelSize) {\n opacity *= size / pixelSize;\n size = pixelSize;\n }\n\n vec2 a = applyOffset(\n applySampleFacet(vec2(getScaled_x(), getScaled_y())),\n vec2(getScaled_xOffset(), getScaled_yOffset())\n );\n vec2 b = applyOffset(\n applySampleFacet(vec2(getScaled_x2(), getScaled_y2())),\n vec2(getScaled_x2Offset(), getScaled_y2Offset())\n );\n\n vec2 tangent = b - a;\n\n float offset = 0.0;\n float relativeDiff = 0.0;\n if (uMinLength > 0.0 || uStrokeCap != BUTT) {\n float len = length(tangent * uViewportSize);\n\n // Elongate to reach the minimum length.\n // The length difference in pixels\n float diff = max(0.0, uMinLength - len);\n\n // Add line caps\n if (uStrokeCap != BUTT) {\n diff += size;\n }\n\n relativeDiff = diff / len;\n offset = relativeDiff * (pos - 0.5);\n }\n\n // Apply caps and minimum length by spreading the vertices along the tangent\n vec2 p = pos < 1.0\n ? a + tangent * (pos + offset)\n : b + tangent * offset;\n\n // Add an extra pixel to stroke width to accommodate edge antialiasing\n float aaPadding = pixelSize;\n\n // Extrude\n vec2 normal = normalize(vec2(-tangent.y, tangent.x) / uViewportSize);\n p += normal * side * (size + aaPadding) / uViewportSize;\n\n gl_Position = unitToNdc(p);\n\n vColor = vec4(getScaled_color() * opacity, opacity);\n vSize = size;\n vNormalLengthInPixels = side * (size + aaPadding);\n\n // TODO: Here's a precision problem that breaks round caps when zoomed in enough\n vPosInPixels = vec2(pos, (1.0 - pos)) * (1.0 + relativeDiff) * length(tangent * uViewportSize) -\n vec2(uStrokeCap != BUTT ? size / 2.0 : 0.0);\n \n setupPicking();\n}\n", dl = "// Line ending\nconst int BUTT = 0;\nconst int SQUARE = 1;\nconst int ROUND = 2;\n\nuniform sampler2D uDashTexture;\n\nflat in vec4 vColor;\nflat in float vSize;\n\n/** Position on the rule along its length in pixels */\nin vec2 vPosInPixels;\nin float vNormalLengthInPixels;\n\nout lowp vec4 fragColor;\n\nvoid main(void) {\n float dpr = uDevicePixelRatio;\n\n float distanceFromEnd = -min(vPosInPixels[0], vPosInPixels[1]);\n float distance; // from the rule centerline or end\n if (distanceFromEnd > 0.0 && uStrokeCap == ROUND) {\n // round cap\n distance = length(vec2(distanceFromEnd, vNormalLengthInPixels));\n } else {\n distance = abs(vNormalLengthInPixels);\n }\n\n // Use a signed distance field to implement edge antialiasing\n float opacity = clamp(((vSize / 2.0 - distance) * dpr), -0.5, 0.5) + 0.5;\n\n if (uDashTextureSize > 0.0) {\n float pos = (vPosInPixels[0] + uStrokeDashOffset) * dpr;\n float floored = floor(pos);\n vec2 texelPositions = (floored + vec2(0.5, 1.5)) / dpr / uDashTextureSize;\n \n // Do antialiasing\n opacity *= mix(\n texture(uDashTexture, vec2(texelPositions[0], 0)).r,\n texture(uDashTexture, vec2(texelPositions[1], 0)).r,\n clamp((pos - floored), 0.0, 1.0));\n }\n\n fragColor = vColor * opacity;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", fl = "layout(std140) uniform Mark {\n /** Minimum rule length in pixels */\n uniform mediump float uMinLength;\n\n uniform mediump float uDashTextureSize;\n uniform lowp int uStrokeCap;\n uniform mediump float uStrokeDashOffset;\n\n#pragma markUniforms\n};\n", pl = class extends Fc {
3806
3827
  constructor(e, t, n) {
3807
3828
  super(e, t, n), this.dashTexture = void 0, this.dashTextureSize = 0;
3808
3829
  }
@@ -3825,7 +3846,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3825
3846
  }
3826
3847
  initializeGraphics() {
3827
3848
  super.initializeGraphics();
3828
- let e = this.gl, t = pl(this.properties.strokeDash);
3849
+ let e = this.gl, t = ml(this.properties.strokeDash);
3829
3850
  this.dashTexture = oi(e, {
3830
3851
  level: 0,
3831
3852
  mag: e.NEAREST,
@@ -3834,7 +3855,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3834
3855
  format: e.RED,
3835
3856
  src: t,
3836
3857
  height: 1
3837
- }), this.dashTextureSize = t.length, this.createAndLinkShaders(ll, ul, [dl]);
3858
+ }), this.dashTextureSize = t.length, this.createAndLinkShaders(ul, dl, [fl]);
3838
3859
  }
3839
3860
  finalizeGraphicsInitialization() {
3840
3861
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
@@ -3867,7 +3888,7 @@ var Jc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
3867
3888
  this.dashTexture &&= (this.gl.deleteTexture(this.dashTexture), void 0), super.dispose();
3868
3889
  }
3869
3890
  };
3870
- function pl(e) {
3891
+ function ml(e) {
3871
3892
  if (!e) return /* @__PURE__ */ new Uint8Array();
3872
3893
  if (e.length == 0 || e.length % 2 || e.findIndex((e) => Math.round(e) != e || e < 1 || e > 1e3) >= 0) throw Error("Invalid stroke dash pattern: " + JSON.stringify(e));
3873
3894
  let t = e.reduce((e, t) => e + t), n = new Uint8Array(t), r = !0, i = 0;
@@ -3879,24 +3900,24 @@ function pl(e) {
3879
3900
  }
3880
3901
  //#endregion
3881
3902
  //#region ../core/src/rendering/webgl/marks/text.vertex.glsl
3882
- var ml = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width of the text (all letters)\nin float width;\n\nout vec2 vTexCoord;\nout float vEdgeFadeOpacity;\nflat out vec4 vColor;\nflat out float vSlope;\nflat out float vGamma;\n\nstruct RangeResult {\n float pos;\n float scale;\n};\n\nfloat minValue(vec4 v) {\n return min(min(v.x, v.y), min(v.z, v.w));\n}\n\nfloat maxValue(vec4 v) {\n return max(max(v.x, v.y), max(v.z, v.w));\n}\n\n/**\n * All measures are in [0, 1]\n */\nRangeResult positionInsideRange(float a, float b, float width, float padding,\n int align, bool flush) {\n float span = b - a;\n float paddedWidth = width + 2.0 * padding;\n\n // Is the text clearly outside the viewport\n if (a > 1.0 || b < 0.0) {\n return RangeResult(0.0, 0.0);\n }\n\n // How much extra space we have for adjusting the position so that the\n // text stays inside the range.\n float extra = max(0.0, span - paddedWidth);\n\n float pos;\n\n // Align the text and try to keep it inside the range and the viewport\n if (align == 0) {\n float centre = a + b;\n\n if (flush) {\n float leftOver = max(0.0, paddedWidth - centre);\n centre += min(leftOver, extra);\n\n float rightOver = max(0.0, paddedWidth + centre - 2.0);\n centre -= min(rightOver, extra);\n }\n\n pos = centre / 2.0;\n\n } else if (align < 0) {\n float edge = a;\n\n if (flush) {\n float over = max(0.0, -edge);\n edge += min(over, extra);\n }\n\n pos = edge + padding;\n\n } else {\n float edge = b;\n\n if (flush) {\n float over = max(0.0, edge - 1.0);\n edge -= min(over, extra);\n }\n\n // TODO: If the text spans the whole viewport, try to keep it centered if possible.\n\n pos = edge - padding;\n }\n\n // How the text should be scaled to make it fit inside the range (if it didn't fit).\n float scale = clamp((span - padding) / paddedWidth, 0.0, 1.0);\n\n // TODO: Fix padding in scale factor. Padding should stay constant\n return RangeResult(pos, scale);\n}\n\nvec2 calculateRotatedDimensions(float width, mat2 rotationMatrix) {\n vec2 a = abs(rotationMatrix * vec2(width / 2.0, 0.5));\n vec2 b = abs(rotationMatrix * vec2(width / 2.0, -0.5));\n return vec2(max(a.x, b.x), max(a.y, b.y)) * 2.0;\n}\n\n/** Needed when using ranged text */\nivec2 fixAlignForAngle(ivec2 align, float angleInDegrees) {\n float a = mod(angleInDegrees + 45.0, 360.0);\n int x = align.x;\n int y = -align.y;\n\n // TODO: Optimize by avoiding branching\n if (a < 90.0) {\n return ivec2(x, y);\n } else if (a < 180.0) {\n return ivec2(y, -x);\n } else if (a < 270.0) {\n return ivec2(-x, y);\n } else {\n return ivec2(-y, x);\n }\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float opacity = getScaled_opacity() * uViewOpacity;\n vec2 size = vec2(getScaled_size());\n float x = getScaled_x() + getScaled_xOffset() / uViewportSize.x;\n float y = getScaled_y();\n\n float scale = 1.0;\n\n float angleInDegrees = getScaled_angle();\n float angle = -angleInDegrees * PI / 180.0;\n \n float sinTheta = sin(angle);\n float cosTheta = cos(angle);\n mat2 rotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);\n\n vec2 flushSize = calculateRotatedDimensions(width, rotationMatrix);\n\n#if defined(x2_DEFINED) || defined(y2_DEFINED)\n ivec2 align = fixAlignForAngle(uAlign, angleInDegrees);\n#else\n ivec2 align = uAlign;\n#endif\n\n#ifdef x2_DEFINED\n float x2 = getScaled_x2() + getScaled_x2Offset() / uViewportSize.x;\n\n if (uLogoLetter) {\n size.x = (x2 - x) * uViewportSize.x;\n x += (x2 - x) / 2.0;\n\n } else {\n RangeResult result = positionInsideRange(\n min(x, x2), max(x, x2),\n size.x * scale * flushSize.x / uViewportSize.x, uPaddingX / uViewportSize.x,\n align.x, uFlushX);\n \n x = result.pos;\n scale *= result.scale;\n }\n#endif\n\n // Position of the text origo \n vec2 pos = applyOffset(\n applySampleFacet(vec2(x, y)),\n vec2(0.0, getScaled_yOffset())\n );\n\n#ifdef y2_DEFINED\n float y2 = getScaled_y2();\n vec2 pos2 = applyOffset(\n applySampleFacet(vec2(x, y2)),\n vec2(0.0, getScaled_y2Offset())\n );\n\n if (uLogoLetter) {\n size.y = (pos2.y - pos.y) * uViewportSize.y;\n pos.y += (pos2.y - pos.y) / 2.0;\n\n } else {\n RangeResult result = positionInsideRange(\n min(pos.y, pos2.y), max(pos.y, pos2.y),\n size.y * scale * flushSize.y / uViewportSize.y, uPaddingY / uViewportSize.y,\n align.y, uFlushY);\n \n pos.y = result.pos;\n scale *= result.scale;\n }\n#endif\n\n#ifdef VISIBLE_RANGE_CULLING\n if (isOutsideVisibleRange(pos)) {\n gl_Position = vec4(0.0);\n return;\n }\n#endif\n\n if (scale < 1.0) {\n if (uSqueeze) {\n vec2 scaleFadeExtent = vec2(3.0, 6.0) / size;\n\n if (scale < scaleFadeExtent[0]) {\n gl_Position = vec4(0.0);\n return;\n }\n\n size *= scale;\n opacity *= linearstep(scaleFadeExtent[0], scaleFadeExtent[1], scale);\n\n } else if (scale < 1.0) {\n // Eliminate the text\n gl_Position = vec4(0.0);\n return;\n }\n }\n\n // Position of the character vertex in relation to the text origo\n vec2 charPos = rotationMatrix * (vertexCoord * size + uD);\n\n // Position of the character vertex inside the unit viewport\n vec2 unitPos = pos + charPos / uViewportSize;\n\n gl_Position = unitToNdc(unitPos);\n\n // Controls antialiasing of the SDF\n vSlope = max(1.0, min(size.x, size.y) / uSdfNumerator * uDevicePixelRatio);\n\n vec3 color = getScaled_color();\n\n // Premultiply alpha\n vColor = vec4(color * opacity, opacity);\n\n // Do something like gamma correction for text when the color is close to black or white.\n vGamma = getGammaForColor(color);\n\n vTexCoord = textureCoord;\n\n // Edge fading. The implementation is simplistic and fails with primitives that\n // span the whole viewport. However, it works just fine with reasonable font sizes.\n // x: top, y: right, z: bottom, w: left\n if (maxValue(uViewportEdgeFadeDistance) > -pow(10.0, 10.0)) { // -Infinity would be nice\n vEdgeFadeOpacity = minValue(\n ((vec4(1.0, 1.0, 0.0, 0.0) + vec4(-1.0, -1.0, 1.0, 1.0) * unitPos.yxyx) *\n uViewportSize.yxyx - uViewportEdgeFadeDistance) / uViewportEdgeFadeWidth);\n } else {\n vEdgeFadeOpacity = 1.0;\n }\n\n setupPicking();\n}\n", hl = "uniform sampler2D uTexture;\n\nin vec2 vTexCoord;\nin float vEdgeFadeOpacity;\nflat in vec4 vColor;\nflat in float vSlope;\nflat in float vGamma;\n\nout lowp vec4 fragColor;\n\nfloat median(float r, float g, float b) {\n return max(min(r, g), min(max(r, g), b));\n}\n\nfloat getDist(vec2 uv) {\n vec3 c = texture(uTexture, uv).rgb;\n return 1.0 - median(c.r, c.g, c.b);\n}\n\n/**\n * Calculates the super-sampled distance to the edge.\n * This is used to avoid aliasing when rendering small text,\n * as mip-mapping cannot be used here.\n * The distance is averaged over a grid of n x n samples.\n */\nfloat getSuperDist(vec2 uv) {\n vec2 dx = dFdx(uv);\n vec2 dy = dFdy(uv);\n\n float n = 2.0;\n\n float sum = 0.0;\n for (float x = 0.5; x < n; x++){\n for (float y = 0.5; y < n; y++) {\n sum += getDist(\n uv +\n x / n * dx +\n y / n * dy\n ); \n }\n }\n\n return sum / (n * n);\n}\n\nvoid main() {\n float sigDist = getSuperDist(vTexCoord);\n\n float slope = vSlope;\n if (uLogoLetter) {\n // Using screen-space derivatives for logo letters because skewed aspect ratios\n // result in blurry edges otherwise. However, use of screen-space derivatives\n // results in crappy looking text with regular letters text.\n slope = 0.7 / length(vec2(dFdy(sigDist), dFdx(sigDist)));\n }\n\n float opa = clamp((sigDist - 0.5) * slope + 0.5, 0.0, 1.0);\n opa *= clamp(vEdgeFadeOpacity, 0.0, 1.0);\n\n opa = pow(opa, vGamma);\n\n fragColor = vColor * opa;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", gl = "layout(std140) uniform Mark {\n uniform mediump float uSdfNumerator;\n\n uniform mediump vec2 uD; // dx & dy\n\n uniform mediump vec4 uViewportEdgeFadeWidth;\n uniform mediump vec4 uViewportEdgeFadeDistance;\n \n uniform bool uSqueeze;\n uniform bool uLogoLetter;\n\n // x: -1, 0, 1 = left, center, right\n // y: -1, 0, 1 = top, middle, bottom \n uniform lowp ivec2 uAlign;\n\n uniform mediump float uPaddingX;\n uniform bool uFlushX;\n uniform mediump float uPaddingY;\n uniform bool uFlushY;\n\n#pragma markUniforms\n};\n", _l = 1024, vl = {
3903
+ var hl = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width of the text (all letters)\nin float width;\n\nout vec2 vTexCoord;\nout float vEdgeFadeOpacity;\nflat out vec4 vColor;\nflat out float vSlope;\nflat out float vGamma;\n\nstruct RangeResult {\n float pos;\n float scale;\n};\n\nfloat minValue(vec4 v) {\n return min(min(v.x, v.y), min(v.z, v.w));\n}\n\nfloat maxValue(vec4 v) {\n return max(max(v.x, v.y), max(v.z, v.w));\n}\n\n/**\n * All measures are in [0, 1]\n */\nRangeResult positionInsideRange(float a, float b, float width, float padding,\n int align, bool flush) {\n float span = b - a;\n float paddedWidth = width + 2.0 * padding;\n\n // Is the text clearly outside the viewport\n if (a > 1.0 || b < 0.0) {\n return RangeResult(0.0, 0.0);\n }\n\n // How much extra space we have for adjusting the position so that the\n // text stays inside the range.\n float extra = max(0.0, span - paddedWidth);\n\n float pos;\n\n // Align the text and try to keep it inside the range and the viewport\n if (align == 0) {\n float centre = a + b;\n\n if (flush) {\n float leftOver = max(0.0, paddedWidth - centre);\n centre += min(leftOver, extra);\n\n float rightOver = max(0.0, paddedWidth + centre - 2.0);\n centre -= min(rightOver, extra);\n }\n\n pos = centre / 2.0;\n\n } else if (align < 0) {\n float edge = a;\n\n if (flush) {\n float over = max(0.0, -edge);\n edge += min(over, extra);\n }\n\n pos = edge + padding;\n\n } else {\n float edge = b;\n\n if (flush) {\n float over = max(0.0, edge - 1.0);\n edge -= min(over, extra);\n }\n\n // TODO: If the text spans the whole viewport, try to keep it centered if possible.\n\n pos = edge - padding;\n }\n\n // How the text should be scaled to make it fit inside the range (if it didn't fit).\n float scale = clamp((span - padding) / paddedWidth, 0.0, 1.0);\n\n // TODO: Fix padding in scale factor. Padding should stay constant\n return RangeResult(pos, scale);\n}\n\nvec2 calculateRotatedDimensions(float width, mat2 rotationMatrix) {\n vec2 a = abs(rotationMatrix * vec2(width / 2.0, 0.5));\n vec2 b = abs(rotationMatrix * vec2(width / 2.0, -0.5));\n return vec2(max(a.x, b.x), max(a.y, b.y)) * 2.0;\n}\n\n/** Needed when using ranged text */\nivec2 fixAlignForAngle(ivec2 align, float angleInDegrees) {\n float a = mod(angleInDegrees + 45.0, 360.0);\n int x = align.x;\n int y = -align.y;\n\n // TODO: Optimize by avoiding branching\n if (a < 90.0) {\n return ivec2(x, y);\n } else if (a < 180.0) {\n return ivec2(y, -x);\n } else if (a < 270.0) {\n return ivec2(-x, y);\n } else {\n return ivec2(-y, x);\n }\n}\n\nvoid main(void) {\n#pragma orderGuard\n\n float opacity = getScaled_opacity() * uViewOpacity;\n vec2 size = vec2(getScaled_size());\n float x = getScaled_x() + getScaled_xOffset() / uViewportSize.x;\n float y = getScaled_y();\n\n float scale = 1.0;\n\n float angleInDegrees = getScaled_angle();\n float angle = -angleInDegrees * PI / 180.0;\n \n float sinTheta = sin(angle);\n float cosTheta = cos(angle);\n mat2 rotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);\n\n vec2 flushSize = calculateRotatedDimensions(width, rotationMatrix);\n\n#if defined(x2_DEFINED) || defined(y2_DEFINED)\n ivec2 align = fixAlignForAngle(uAlign, angleInDegrees);\n#else\n ivec2 align = uAlign;\n#endif\n\n#ifdef x2_DEFINED\n float x2 = getScaled_x2() + getScaled_x2Offset() / uViewportSize.x;\n\n if (uLogoLetter) {\n size.x = (x2 - x) * uViewportSize.x;\n x += (x2 - x) / 2.0;\n\n } else {\n RangeResult result = positionInsideRange(\n min(x, x2), max(x, x2),\n size.x * scale * flushSize.x / uViewportSize.x, uPaddingX / uViewportSize.x,\n align.x, uFlushX);\n \n x = result.pos;\n scale *= result.scale;\n }\n#endif\n\n // Position of the text origo \n vec2 pos = applyOffset(\n applySampleFacet(vec2(x, y)),\n vec2(0.0, getScaled_yOffset())\n );\n\n#ifdef y2_DEFINED\n float y2 = getScaled_y2();\n vec2 pos2 = applyOffset(\n applySampleFacet(vec2(x, y2)),\n vec2(0.0, getScaled_y2Offset())\n );\n\n if (uLogoLetter) {\n size.y = (pos2.y - pos.y) * uViewportSize.y;\n pos.y += (pos2.y - pos.y) / 2.0;\n\n } else {\n RangeResult result = positionInsideRange(\n min(pos.y, pos2.y), max(pos.y, pos2.y),\n size.y * scale * flushSize.y / uViewportSize.y, uPaddingY / uViewportSize.y,\n align.y, uFlushY);\n \n pos.y = result.pos;\n scale *= result.scale;\n }\n#endif\n\n#ifdef VISIBLE_RANGE_CULLING\n if (isOutsideVisibleRange(pos)) {\n gl_Position = vec4(0.0);\n return;\n }\n#endif\n\n if (scale < 1.0) {\n if (uSqueeze) {\n vec2 scaleFadeExtent = vec2(3.0, 6.0) / size;\n\n if (scale < scaleFadeExtent[0]) {\n gl_Position = vec4(0.0);\n return;\n }\n\n size *= scale;\n opacity *= linearstep(scaleFadeExtent[0], scaleFadeExtent[1], scale);\n\n } else if (scale < 1.0) {\n // Eliminate the text\n gl_Position = vec4(0.0);\n return;\n }\n }\n\n // Position of the character vertex in relation to the text origo\n vec2 charPos = rotationMatrix * (vertexCoord * size + uD);\n\n // Position of the character vertex inside the unit viewport\n vec2 unitPos = pos + charPos / uViewportSize;\n\n gl_Position = unitToNdc(unitPos);\n\n // Controls antialiasing of the SDF\n vSlope = max(1.0, min(size.x, size.y) / uSdfNumerator * uDevicePixelRatio);\n\n vec3 color = getScaled_color();\n\n // Premultiply alpha\n vColor = vec4(color * opacity, opacity);\n\n // Do something like gamma correction for text when the color is close to black or white.\n vGamma = getGammaForColor(color);\n\n vTexCoord = textureCoord;\n\n // Edge fading. The implementation is simplistic and fails with primitives that\n // span the whole viewport. However, it works just fine with reasonable font sizes.\n // x: top, y: right, z: bottom, w: left\n if (maxValue(uViewportEdgeFadeDistance) > -pow(10.0, 10.0)) { // -Infinity would be nice\n vEdgeFadeOpacity = minValue(\n ((vec4(1.0, 1.0, 0.0, 0.0) + vec4(-1.0, -1.0, 1.0, 1.0) * unitPos.yxyx) *\n uViewportSize.yxyx - uViewportEdgeFadeDistance) / uViewportEdgeFadeWidth);\n } else {\n vEdgeFadeOpacity = 1.0;\n }\n\n setupPicking();\n}\n", gl = "uniform sampler2D uTexture;\n\nin vec2 vTexCoord;\nin float vEdgeFadeOpacity;\nflat in vec4 vColor;\nflat in float vSlope;\nflat in float vGamma;\n\nout lowp vec4 fragColor;\n\nfloat median(float r, float g, float b) {\n return max(min(r, g), min(max(r, g), b));\n}\n\nfloat getDist(vec2 uv) {\n vec3 c = texture(uTexture, uv).rgb;\n return 1.0 - median(c.r, c.g, c.b);\n}\n\n/**\n * Calculates the super-sampled distance to the edge.\n * This is used to avoid aliasing when rendering small text,\n * as mip-mapping cannot be used here.\n * The distance is averaged over a grid of n x n samples.\n */\nfloat getSuperDist(vec2 uv) {\n vec2 dx = dFdx(uv);\n vec2 dy = dFdy(uv);\n\n float n = 2.0;\n\n float sum = 0.0;\n for (float x = 0.5; x < n; x++){\n for (float y = 0.5; y < n; y++) {\n sum += getDist(\n uv +\n x / n * dx +\n y / n * dy\n ); \n }\n }\n\n return sum / (n * n);\n}\n\nvoid main() {\n float sigDist = getSuperDist(vTexCoord);\n\n float slope = vSlope;\n if (uLogoLetter) {\n // Using screen-space derivatives for logo letters because skewed aspect ratios\n // result in blurry edges otherwise. However, use of screen-space derivatives\n // results in crappy looking text with regular letters text.\n slope = 0.7 / length(vec2(dFdy(sigDist), dFdx(sigDist)));\n }\n\n float opa = clamp((sigDist - 0.5) * slope + 0.5, 0.0, 1.0);\n opa *= clamp(vEdgeFadeOpacity, 0.0, 1.0);\n\n opa = pow(opa, vGamma);\n\n fragColor = vColor * opa;\n\n if (uPickingEnabled) {\n fragColor = vPickingColor;\n }\n}\n", _l = "layout(std140) uniform Mark {\n uniform mediump float uSdfNumerator;\n\n uniform mediump vec2 uD; // dx & dy\n\n uniform mediump vec4 uViewportEdgeFadeWidth;\n uniform mediump vec4 uViewportEdgeFadeDistance;\n \n uniform bool uSqueeze;\n uniform bool uLogoLetter;\n\n // x: -1, 0, 1 = left, center, right\n // y: -1, 0, 1 = top, middle, bottom \n uniform lowp ivec2 uAlign;\n\n uniform mediump float uPaddingX;\n uniform bool uFlushX;\n uniform mediump float uPaddingY;\n uniform bool uFlushY;\n\n#pragma markUniforms\n};\n", vl = 1024, yl = {
3883
3904
  left: -1,
3884
3905
  center: 0,
3885
3906
  right: 1
3886
- }, yl = {
3907
+ }, bl = {
3887
3908
  top: -1,
3888
3909
  middle: 0,
3889
3910
  bottom: 1,
3890
3911
  alphabetic: 1,
3891
3912
  baseline: 1
3892
- }, bl = {
3893
- point: rl,
3894
- rect: cl,
3895
- arrow: Wc,
3896
- rule: fl,
3897
- tick: fl,
3898
- link: $c,
3899
- text: class extends Pc {
3913
+ }, xl = {
3914
+ point: il,
3915
+ rect: ll,
3916
+ arrow: Gc,
3917
+ rule: pl,
3918
+ tick: pl,
3919
+ link: el,
3920
+ text: class extends Fc {
3900
3921
  getAttributes() {
3901
3922
  return [
3902
3923
  "uniqueId",
@@ -3916,7 +3937,7 @@ var ml = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
3916
3937
  ];
3917
3938
  }
3918
3939
  initializeGraphics() {
3919
- super.initializeGraphics(), this.createAndLinkShaders(ml, hl, [gl]);
3940
+ super.initializeGraphics(), this.createAndLinkShaders(hl, gl, [_l]);
3920
3941
  }
3921
3942
  finalizeGraphicsInitialization() {
3922
3943
  super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
@@ -3932,7 +3953,7 @@ var ml = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
3932
3953
  e.viewportEdgeFadeDistanceBottom,
3933
3954
  e.viewportEdgeFadeDistanceLeft
3934
3955
  ]), eo(this.markUniformInfo, {
3935
- uAlign: [vl[e.align], yl[e.baseline]],
3956
+ uAlign: [yl[e.align], bl[e.baseline]],
3936
3957
  uD: [e.dx, -e.dy]
3937
3958
  });
3938
3959
  }
@@ -3956,7 +3977,7 @@ var ml = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
3956
3977
  logoLetters: a
3957
3978
  },
3958
3979
  fontMetrics: this.font.metrics,
3959
- numCharacters: Math.max(s, _l)
3980
+ numCharacters: Math.max(s, vl)
3960
3981
  });
3961
3982
  l.addBatches(e.facetBatches);
3962
3983
  let u = l.toArrays();
@@ -3974,12 +3995,12 @@ var ml = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
3974
3995
  }
3975
3996
  }
3976
3997
  };
3977
- function xl(e, t, n) {
3978
- let r = bl[e.getType()];
3998
+ function Sl(e, t, n) {
3999
+ let r = xl[e.getType()];
3979
4000
  if (!r) throw Error("Unsupported WebGL mark type: " + e.getType());
3980
4001
  return new r(e, t, n);
3981
4002
  }
3982
- var Sl = class {
4003
+ var Cl = class {
3983
4004
  #e = !1;
3984
4005
  #t = /* @__PURE__ */ new Map();
3985
4006
  #n = /* @__PURE__ */ new Map();
@@ -3989,7 +4010,7 @@ var Sl = class {
3989
4010
  }
3990
4011
  #i(e) {
3991
4012
  this.#s();
3992
- let t = xl(e, this.glHelper, this), n = {
4013
+ let t = Sl(e, this.glHelper, this), n = {
3993
4014
  mark: e,
3994
4015
  graphics: t,
3995
4016
  state: "compiling",
@@ -4020,7 +4041,7 @@ var Sl = class {
4020
4041
  this.#s();
4021
4042
  let t = [], n;
4022
4043
  for (let r of new Set(e)) try {
4023
- let e = r.getType() != "text" || Oc(r).metrics;
4044
+ let e = r.getType() != "text" || kc(r).metrics;
4024
4045
  !this.#t.has(r) && r.encoders && e && t.push(this.#i(r));
4025
4046
  } catch (e) {
4026
4047
  n ??= e;
@@ -4140,9 +4161,9 @@ var Sl = class {
4140
4161
  };
4141
4162
  //#endregion
4142
4163
  //#region ../core/src/rendering/webgl/svgRasterizer.js
4143
- function Cl({ runs: e, viewRoot: t, layoutResult: n, webGLHelper: r, markAdapter: i, logicalWidth: a, logicalHeight: o, pixelRatio: s }) {
4164
+ function wl({ runs: e, viewRoot: t, layoutResult: n, webGLHelper: r, markAdapter: i, logicalWidth: a, logicalHeight: o, pixelRatio: s }) {
4144
4165
  let c = r.gl, l = Math.ceil(a * s), u = Math.ceil(o * s);
4145
- wl(c, l, u);
4166
+ Tl(c, l, u);
4146
4167
  let d = s == 1 && n ? n : Te(t, xe.create(0, 0, a, o), {
4147
4168
  devicePixelRatio: s,
4148
4169
  renderingOptions: { firstFacet: !0 }
@@ -4177,11 +4198,11 @@ function Cl({ runs: e, viewRoot: t, layoutResult: n, webGLHelper: r, markAdapter
4177
4198
  c.bindFramebuffer(c.FRAMEBUFFER, null), c.deleteTexture(f.attachments[0]), c.deleteFramebuffer(f.framebuffer);
4178
4199
  }
4179
4200
  }
4180
- function wl(e, t, n) {
4201
+ function Tl(e, t, n) {
4181
4202
  let r = e.getParameter(e.MAX_RENDERBUFFER_SIZE), i = e.getParameter(e.MAX_TEXTURE_SIZE), a = Math.min(r, i);
4182
4203
  if (t <= 0 || n <= 0 || t > a || n > a) throw RangeError(`SVG raster dimensions ${t} x ${n} exceed the WebGL limit ${a}.`);
4183
4204
  }
4184
- var Tl = {
4205
+ var El = {
4185
4206
  pages: ["Lato-Regular.png"],
4186
4207
  chars: [
4187
4208
  {
@@ -5356,7 +5377,7 @@ var Tl = {
5356
5377
  blueChnl: 0
5357
5378
  },
5358
5379
  kernings: []
5359
- }, El = {
5380
+ }, Dl = {
5360
5381
  thin: 100,
5361
5382
  light: 300,
5362
5383
  regular: 400,
@@ -5364,25 +5385,25 @@ var Tl = {
5364
5385
  medium: 500,
5365
5386
  bold: 700,
5366
5387
  black: 900
5367
- }, Dl = {
5388
+ }, Ol = {
5368
5389
  family: "Lato",
5369
5390
  style: "normal",
5370
5391
  weight: 400
5371
- }, Ol = class {
5392
+ }, kl = class {
5372
5393
  constructor(e, t) {
5373
5394
  this._prepareBitmap = e, this.fontRepository = "https://raw.githubusercontent.com/etiennepinchon/aframe-fonts/master/fonts/", this._fonts = new x([], JSON.stringify), this._metadataPromises = /* @__PURE__ */ new Map(), this._fontPromises = /* @__PURE__ */ new Map(), this._promises = [];
5374
5395
  let n = t && e?.(t);
5375
5396
  this._defaultFontEntry = {
5376
- metrics: fc(Tl),
5397
+ metrics: fc(El),
5377
5398
  bitmapUrl: t,
5378
5399
  measurement: void 0
5379
- }, this._defaultFontEntry.measurement = this._createMeasurement(this._defaultFontEntry), n && this._promises.push(n), this._fonts.set(Dl, this._defaultFontEntry);
5400
+ }, this._defaultFontEntry.measurement = this._createMeasurement(this._defaultFontEntry), n && this._promises.push(n), this._fonts.set(Ol, this._defaultFontEntry);
5380
5401
  }
5381
5402
  async waitUntilReady() {
5382
5403
  await Promise.all(this._promises);
5383
5404
  }
5384
- getFont(e = Dl.family, t = "normal", n = 400) {
5385
- let r = kl(e, t, n), i = this._fonts.get(r);
5405
+ getFont(e = Ol.family, t = "normal", n = 400) {
5406
+ let r = Al(e, t, n), i = this._fonts.get(r);
5386
5407
  return i || (i = {
5387
5408
  metrics: void 0,
5388
5409
  bitmapUrl: void 0,
@@ -5404,7 +5425,7 @@ var Tl = {
5404
5425
  }
5405
5426
  async _loadFontEntry(e, t) {
5406
5427
  try {
5407
- let n = Nl(await this._loadMetadata(t.family), t), r = this.fontRepository + jl(t.family) + "/" + n.replace(/\.\w+/, "");
5428
+ let n = Pl(await this._loadMetadata(t.family), t), r = this.fontRepository + Ml(t.family) + "/" + n.replace(/\.\w+/, "");
5408
5429
  e.bitmapUrl = r + ".png";
5409
5430
  let i = this._loadFont(r + ".json"), a = this._prepareBitmap?.(e.bitmapUrl), [o] = await Promise.all([i, a]);
5410
5431
  e.metrics = o;
@@ -5420,13 +5441,13 @@ var Tl = {
5420
5441
  }).then((e) => e.json()).then((e) => fc(e)), this._fontPromises.set(e, t)), t;
5421
5442
  }
5422
5443
  _loadMetadata(e) {
5423
- let t = jl(e), n = this._metadataPromises.get(t);
5444
+ let t = Ml(e), n = this._metadataPromises.get(t);
5424
5445
  if (!n) {
5425
5446
  let e = this.fontRepository + t + "/METADATA.pb";
5426
5447
  n = fetch(e).then((t) => {
5427
5448
  if (!t.ok) throw Error("Could not load font metadata. Response status: " + t.status + ", url: " + e);
5428
5449
  return t;
5429
- }).then((e) => e.text()).then((e) => Ml(e)).catch((e) => {
5450
+ }).then((e) => e.text()).then((e) => Nl(e)).catch((e) => {
5430
5451
  console.warn(e.message);
5431
5452
  }), this._metadataPromises.set(t, n);
5432
5453
  }
@@ -5436,25 +5457,25 @@ var Tl = {
5436
5457
  return this._defaultFontEntry;
5437
5458
  }
5438
5459
  };
5439
- function kl(e, t, n) {
5460
+ function Al(e, t, n) {
5440
5461
  return {
5441
- family: e.toLowerCase() == "sans-serif" ? Dl.family : e,
5462
+ family: e.toLowerCase() == "sans-serif" ? Ol.family : e,
5442
5463
  style: t,
5443
- weight: Al(n)
5464
+ weight: jl(n)
5444
5465
  };
5445
5466
  }
5446
- function Al(e) {
5467
+ function jl(e) {
5447
5468
  if (C(e)) {
5448
- let t = El[e.toLowerCase()];
5469
+ let t = Dl[e.toLowerCase()];
5449
5470
  if (!t) throw Error("Unknown font weight: " + e);
5450
5471
  return t;
5451
5472
  }
5452
5473
  return e;
5453
5474
  }
5454
- function jl(e) {
5475
+ function Ml(e) {
5455
5476
  return e.toLowerCase().replaceAll(/[^\w]/g, "");
5456
5477
  }
5457
- function Ml(e) {
5478
+ function Nl(e) {
5458
5479
  let t = e.split("\n"), n = [], r;
5459
5480
  for (let e of t) if (e.startsWith("fonts {") && (r = {
5460
5481
  name: void 0,
@@ -5477,7 +5498,7 @@ function Ml(e) {
5477
5498
  }
5478
5499
  return n;
5479
5500
  }
5480
- function Nl(e, t) {
5501
+ function Pl(e, t) {
5481
5502
  let n, r = Infinity;
5482
5503
  for (let i of e) if (t.family.localeCompare(i.name, void 0, { sensitivity: "accent" }) == 0 && t.style == i.style) {
5483
5504
  let e = Math.abs(t.weight - i.weight);
@@ -5487,11 +5508,11 @@ function Nl(e, t) {
5487
5508
  }
5488
5509
  //#endregion
5489
5510
  //#region ../core/src/rendering/webgl/index.js
5490
- function Pl(e) {
5491
- let t = new Hs(e.container, e.sizeSource, { powerPreference: e.powerPreference }, e.onCanvasResize), n = new Sl(t);
5511
+ function Fl(e) {
5512
+ let t = new Hs(e.container, e.sizeSource, { powerPreference: e.powerPreference }, e.onCanvasResize), n = new Cl(t);
5492
5513
  return {
5493
5514
  surface: t,
5494
- textMetrics: new Ol((e) => n.prepareFontBitmap(e), ke),
5515
+ textMetrics: new kl((e) => n.prepareFontBitmap(e), ke),
5495
5516
  getMarkRenderingDebugState: (e) => n.getMarkRenderingDebugState(e),
5496
5517
  createRenderCoordinator: (e) => new Ys({
5497
5518
  ...e,
@@ -5508,7 +5529,7 @@ function Pl(e) {
5508
5529
  glHelper: t,
5509
5530
  markAdapter: n
5510
5531
  }),
5511
- rasterizeSvgRuns: (e) => Cl({
5532
+ rasterizeSvgRuns: (e) => wl({
5512
5533
  ...e,
5513
5534
  webGLHelper: t,
5514
5535
  markAdapter: n
@@ -5520,4 +5541,4 @@ function Pl(e) {
5520
5541
  };
5521
5542
  }
5522
5543
  //#endregion
5523
- export { Pl as createWebGLRenderingBackend };
5544
+ export { Fl as createWebGLRenderingBackend };