@genome-spy/app 1.1.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.
- package/dist/{agentApi-BgZUOeB-.js → agentApi-sPuuT0KS.js} +3297 -3244
- package/dist/agentApi.es.js +1438 -1384
- package/dist/agentShared.es.js +2 -2
- package/dist/{canvas2d-t_N10CeW.js → canvas2d-MXaFeZnP.js} +4 -4
- package/dist/{canvas2d-DiPQvNtZ.js → canvas2d-iDK4BC5j.js} +4 -4
- package/dist/{debug-CVAlrcZt.js → debug-BlqDxTw3.js} +2 -2
- package/dist/{debug-DP4WzTNo.js → debug-DbigmdrK.js} +2 -2
- package/dist/index.es.js +2893 -2891
- package/dist/index.js +342 -342
- package/dist/{order-R043xTpC.js → order-B4uR9Q04.js} +1 -1
- package/dist/{order-BkYCnwD7.js → order-BSPy5DI8.js} +1 -1
- package/dist/{rasterExport-C_FcNBkC.js → rasterExport-B62RmAK1.js} +3 -3
- package/dist/{rasterExport-Z7gs5346.js → rasterExport-DQH3hVg_.js} +3 -3
- package/dist/{rasterization-_-9JmSas.js → rasterization-B05bDo5e.js} +15 -18
- package/dist/rasterization-CFogVB3B.js +50 -0
- package/dist/{renderCanvas2D-IM-A9DYG.js → renderCanvas2D-Bdv-B4wj.js} +15 -15
- package/dist/{renderCanvas2D-DK1c9TFK.js → renderCanvas2D-ChdoHGrU.js} +15 -15
- package/dist/scalePosition-ByvlXaML.js +11 -0
- package/dist/{svg-PabUdcDi.js → svg-DHsq1RpV.js} +13 -13
- package/dist/{svg-DW3tfUmm.js → svg-N3tj05-e.js} +13 -13
- package/dist/{svgRasterizer-BEVDyyS3.js → svgRasterizer-CYVDlt5z.js} +2 -2
- package/dist/{svgRasterizer-B6YtWLJs.js → svgRasterizer-CvCBlxLj.js} +2 -2
- package/dist/{viewIdentityRegistry-BW415b3o.js → viewIdentityRegistry-BDKkEjXl.js} +1 -1
- package/dist/{viewIdentityRegistry-_F0E7nkA.js → viewIdentityRegistry-BIYd4TE0.js} +1 -1
- package/dist/{viewSelectors-KtD-QSN0.js → viewSelectors-DDLW-byr.js} +80 -50
- package/dist/{viewSelectors-DYz-PhTO.js → viewSelectors-j-F9XwsE.js} +80 -50
- package/dist/{viewUtils-BZGPseMx.js → viewUtils-JX6CMEYH.js} +1212 -1211
- package/dist/{webgl-BKSGqHaz.js → webgl-DdmOwEH0.js} +107 -86
- package/dist/{webgl-tdKf9SlZ.js → webgl-Dw8xqZpX.js} +107 -86
- package/package.json +4 -4
|
@@ -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
|
+
}), Xa(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
|
|
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
|
|
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
|
|
3181
|
+
function Pc(e, t) {
|
|
3161
3182
|
return e.replace(/#pragma orderGuard(?:[ \t]*\r?\n){0,2}/, t);
|
|
3162
3183
|
}
|
|
3163
|
-
var
|
|
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
|
|
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
|
|
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
|
|
3201
|
-
if (this.unitView.usesSampleFacetRendering()) return
|
|
3221
|
+
if (this.encoders.facetIndex) return jc;
|
|
3222
|
+
if (this.unitView.usesSampleFacetRendering()) return Ac;
|
|
3202
3223
|
}
|
|
3203
3224
|
createAndLinkShaders(t, r, o = []) {
|
|
3204
3225
|
let c = this.getAttributes(), p = this.encoders, h = this.mark.getOrder(), g = this.getSampleFacetMode(), _ = !!this.properties.cullByVisibleRange;
|
|
@@ -3222,7 +3243,7 @@ var Pc = class {
|
|
|
3222
3243
|
this.registerMarkUniformValue(e, { expr: t }, (e) => e.uniqueId ?? 0);
|
|
3223
3244
|
}), y.push(`bool ${os}${t}() {\n return ${as}${t} != 0u && ${as}${t} == ${i};\n}`), y.push(`bool ${ss}${t}() {\n return ${as}${t} == 0u;\n}`);
|
|
3224
3245
|
} else if (m(r)) {
|
|
3225
|
-
let e =
|
|
3246
|
+
let e = Mc + d(t);
|
|
3226
3247
|
y.push(`// Selection texture\nuniform highp usampler2D ${e};`);
|
|
3227
3248
|
let a = this.glHelper, o = 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 "${t}"!`);
|
|
3231
3252
|
Y(this.programInfo, { [e]: i });
|
|
3232
3253
|
});
|
|
3233
|
-
let s =
|
|
3254
|
+
let s = Mc + t;
|
|
3234
3255
|
y.push(`bool ${os}${t}() {\n return hashContainsTexture(${s}, ${i});\n}`), y.push(`bool ${ss}${t}() {\n return isEmptyHashTexture(${s});\n}`), a.createSelectionTexture(r), n.watchExpression(t, () => {
|
|
3235
3256
|
let e = n.getValue(t);
|
|
3236
3257
|
a.createSelectionTexture(e), this.unitView.context.animator.requestRender();
|
|
@@ -3311,7 +3332,7 @@ var Pc = class {
|
|
|
3311
3332
|
return ${e};\n}`);
|
|
3312
3333
|
}
|
|
3313
3334
|
let ce = "precision highp float;\nprecision highp int;", le = (e) => e.replace("#pragma markUniforms", C.join("\n"));
|
|
3314
|
-
o = o.map(le), t = le(t), r = le(r), t = ((e) =>
|
|
3335
|
+
o = o.map(le), t = le(t), r = le(r), t = ((e) => Pc(e, h ? " if (uOrderMode != 0 &&\n (((uOrderMode & 3) == 1) != isOrderMatch())) {\n gl_Position = vec4(100.0, 0.0, 0.0, 0.0);\n return;\n }" : ""))(t);
|
|
3315
3336
|
let de = [
|
|
3316
3337
|
ce,
|
|
3317
3338
|
v,
|
|
@@ -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 = ro(this.gl, this.programStatus.program), delete this.programStatus, this.viewUniformInfo =
|
|
3366
|
+
this.programInfo = ro(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), Y(this.programInfo, {
|
|
3346
3367
|
uSampleFacet: [0, 1],
|
|
3347
3368
|
uZero: 0
|
|
3348
3369
|
});
|
|
@@ -3419,7 +3440,7 @@ var Pc = class {
|
|
|
3419
3440
|
this.markUniformsAltered ? (Qa(this.gl, this.programInfo, this.markUniformInfo), this.markUniformsAltered = !1) : Za(this.gl, this.programInfo, this.markUniformInfo);
|
|
3420
3441
|
}
|
|
3421
3442
|
setOrderPass(e, t = !1) {
|
|
3422
|
-
$a(this.markUniformInfo, { uOrderMode:
|
|
3443
|
+
$a(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(() => Y(this.programInfo, { [is + e]: i }));
|
|
3432
3453
|
}
|
|
3433
|
-
r.push(...this.selectionTextureOps), this.getSampleFacetMode() ==
|
|
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
|
Y(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 =
|
|
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 =
|
|
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 $a(this.viewUniformInfo, {
|
|
3495
3516
|
...u,
|
|
3496
3517
|
uViewportSize: [n.width, n.height],
|
|
3497
|
-
uLogicalVisibleRect:
|
|
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
|
}), Qa(this.gl, this.programInfo, this.viewUniformInfo), !0;
|
|
3501
3522
|
}
|
|
3502
|
-
},
|
|
3523
|
+
}, Ic = class extends t {
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
],
|
|
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(
|
|
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) =>
|
|
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
|
X(t, this.programInfo, this.bufferInfo), t.drawArraysInstanced(t.TRIANGLE_STRIP, 0, n(), r);
|
|
3672
3693
|
}, e);
|
|
3673
3694
|
}
|
|
3674
|
-
},
|
|
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(
|
|
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 && oo(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
|
-
],
|
|
3765
|
+
], ll = class extends Fc {
|
|
3745
3766
|
get opaque() {
|
|
3746
3767
|
return le(this, "opaque", () => !this.#e() && !this.#t() && !this.properties.shadowOpacity && a(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(
|
|
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,
|
|
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
|
oo(t, this.vertexArrayInfo, t.TRIANGLE_STRIP, n, e);
|
|
3803
3824
|
}, e);
|
|
3804
3825
|
}
|
|
3805
|
-
},
|
|
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 =
|
|
3849
|
+
let e = this.gl, t = ml(this.properties.strokeDash);
|
|
3829
3850
|
this.dashTexture = ai(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(
|
|
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
|
|
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
|
|
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
|
-
},
|
|
3907
|
+
}, bl = {
|
|
3887
3908
|
top: -1,
|
|
3888
3909
|
middle: 0,
|
|
3889
3910
|
bottom: 1,
|
|
3890
3911
|
alphabetic: 1,
|
|
3891
3912
|
baseline: 1
|
|
3892
|
-
},
|
|
3893
|
-
point:
|
|
3894
|
-
rect:
|
|
3895
|
-
arrow:
|
|
3896
|
-
rule:
|
|
3897
|
-
tick:
|
|
3898
|
-
link:
|
|
3899
|
-
text: class extends
|
|
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(
|
|
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
|
]), $a(this.markUniformInfo, {
|
|
3935
|
-
uAlign: [
|
|
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: i
|
|
3957
3978
|
},
|
|
3958
3979
|
fontMetrics: this.font.metrics,
|
|
3959
|
-
numCharacters: Math.max(s,
|
|
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
|
|
3978
|
-
let r =
|
|
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
|
|
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 =
|
|
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" ||
|
|
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
|
|
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
|
-
|
|
4166
|
+
Tl(c, l, u);
|
|
4146
4167
|
let d = s == 1 && n ? n : Se(t, be.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
|
|
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
|
|
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
|
-
},
|
|
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
|
-
},
|
|
5388
|
+
}, Ol = {
|
|
5368
5389
|
family: "Lato",
|
|
5369
5390
|
style: "normal",
|
|
5370
5391
|
weight: 400
|
|
5371
|
-
},
|
|
5392
|
+
}, kl = class {
|
|
5372
5393
|
constructor(e, n) {
|
|
5373
5394
|
this._prepareBitmap = e, this.fontRepository = "https://raw.githubusercontent.com/etiennepinchon/aframe-fonts/master/fonts/", this._fonts = new t([], JSON.stringify), this._metadataPromises = /* @__PURE__ */ new Map(), this._fontPromises = /* @__PURE__ */ new Map(), this._promises = [];
|
|
5374
5395
|
let r = n && e?.(n);
|
|
5375
5396
|
this._defaultFontEntry = {
|
|
5376
|
-
metrics: fc(
|
|
5397
|
+
metrics: fc(El),
|
|
5377
5398
|
bitmapUrl: n,
|
|
5378
5399
|
measurement: void 0
|
|
5379
|
-
}, this._defaultFontEntry.measurement = this._createMeasurement(this._defaultFontEntry), r && this._promises.push(r), this._fonts.set(
|
|
5400
|
+
}, this._defaultFontEntry.measurement = this._createMeasurement(this._defaultFontEntry), r && this._promises.push(r), this._fonts.set(Ol, this._defaultFontEntry);
|
|
5380
5401
|
}
|
|
5381
5402
|
async waitUntilReady() {
|
|
5382
5403
|
await Promise.all(this._promises);
|
|
5383
5404
|
}
|
|
5384
|
-
getFont(e =
|
|
5385
|
-
let 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 =
|
|
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 =
|
|
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) =>
|
|
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
|
|
5460
|
+
function Al(e, t, n) {
|
|
5440
5461
|
return {
|
|
5441
|
-
family: e.toLowerCase() == "sans-serif" ?
|
|
5462
|
+
family: e.toLowerCase() == "sans-serif" ? Ol.family : e,
|
|
5442
5463
|
style: t,
|
|
5443
|
-
weight:
|
|
5464
|
+
weight: jl(n)
|
|
5444
5465
|
};
|
|
5445
5466
|
}
|
|
5446
|
-
function
|
|
5467
|
+
function jl(e) {
|
|
5447
5468
|
if (w(e)) {
|
|
5448
|
-
let t =
|
|
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
|
|
5475
|
+
function Ml(e) {
|
|
5455
5476
|
return e.toLowerCase().replaceAll(/[^\w]/g, "");
|
|
5456
5477
|
}
|
|
5457
|
-
function
|
|
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
|
|
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
|
|
5491
|
-
let t = new Hs(e.container, e.sizeSource, { powerPreference: e.powerPreference }, e.onCanvasResize), n = new
|
|
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
|
|
5515
|
+
textMetrics: new kl((e) => n.prepareFontBitmap(e), Oe),
|
|
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) =>
|
|
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 {
|
|
5544
|
+
export { Fl as createWebGLRenderingBackend };
|