@genome-spy/app 0.88.0 → 0.88.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-BYFBKiRQ.js → agentApi-BIpg3JKh.js} +1 -1
- package/dist/agentApi.es.js +1 -1
- package/dist/index.es.js +7 -7
- package/dist/index.js +329 -331
- package/dist/{webgl-jaC2m0Zr.js → webgl-CTJt7jQd.js} +56 -52
- package/dist/{webgl-CqTDifWM.js → webgl-tZfZ8y3q.js} +56 -52
- package/package.json +5 -5
|
@@ -3100,11 +3100,15 @@ var pc = class {
|
|
|
3100
3100
|
all: 0,
|
|
3101
3101
|
matching: 1,
|
|
3102
3102
|
nonmatching: 2
|
|
3103
|
-
}
|
|
3103
|
+
};
|
|
3104
|
+
function kc(e, t) {
|
|
3105
|
+
return e.replace(/#pragma orderGuard(?:[ \t]*\r?\n){0,2}/, t);
|
|
3106
|
+
}
|
|
3107
|
+
var Ac = class {
|
|
3104
3108
|
#e = [];
|
|
3105
3109
|
#t = !1;
|
|
3106
3110
|
constructor(e, t, n) {
|
|
3107
|
-
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
|
|
3111
|
+
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 jc();
|
|
3108
3112
|
}
|
|
3109
3113
|
get unitView() {
|
|
3110
3114
|
return this.mark.unitView;
|
|
@@ -3250,7 +3254,7 @@ var pc = class {
|
|
|
3250
3254
|
return ${e.join(" || ")};\n}`);
|
|
3251
3255
|
}
|
|
3252
3256
|
let oe = "precision highp float;\nprecision highp int;", ce = (e) => e.replace("#pragma markUniforms", S.join("\n"));
|
|
3253
|
-
d = d.map(ce), n = ce(n), s = ce(s), n = ((e) => e
|
|
3257
|
+
d = d.map(ce), n = ce(n), s = ce(s), n = ((e) => kc(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 }" : ""))(n);
|
|
3254
3258
|
let ue = [
|
|
3255
3259
|
oe,
|
|
3256
3260
|
v,
|
|
@@ -3410,7 +3414,7 @@ var pc = class {
|
|
|
3410
3414
|
}
|
|
3411
3415
|
setViewport(e, t, n, r, i, a = wc) {
|
|
3412
3416
|
n = n.flatten();
|
|
3413
|
-
let o = this.gl, s = this.properties, c = a, l = a, u, d =
|
|
3417
|
+
let o = this.gl, s = this.properties, c = a, l = a, u, d = Mc(e, n, s.clip === "never" ? void 0 : r, !1), f = d.coords;
|
|
3414
3418
|
if (d.requiresScissor) {
|
|
3415
3419
|
if (!f.isDefined()) return !1;
|
|
3416
3420
|
let r = [
|
|
@@ -3433,12 +3437,12 @@ var pc = class {
|
|
|
3433
3437
|
return $a(this.viewUniformInfo, {
|
|
3434
3438
|
...u,
|
|
3435
3439
|
uViewportSize: [n.width, n.height],
|
|
3436
|
-
uLogicalVisibleRect:
|
|
3440
|
+
uLogicalVisibleRect: Nc(n, i),
|
|
3437
3441
|
uCullByVisibleRange: [+(s.cullByVisibleRange === !0 || s.cullByVisibleRange === "x"), +(s.cullByVisibleRange === !0 || s.cullByVisibleRange === "y")],
|
|
3438
3442
|
uDevicePixelRatio: t
|
|
3439
3443
|
}), Qa(this.gl, this.programInfo, this.viewUniformInfo), !0;
|
|
3440
3444
|
}
|
|
3441
|
-
},
|
|
3445
|
+
}, jc = class extends fe {
|
|
3442
3446
|
constructor() {
|
|
3443
3447
|
super([], JSON.stringify);
|
|
3444
3448
|
}
|
|
@@ -3455,7 +3459,7 @@ var pc = class {
|
|
|
3455
3459
|
for (let [t, n] of e.entries()) Object.assign(this.get(t), n);
|
|
3456
3460
|
}
|
|
3457
3461
|
};
|
|
3458
|
-
function
|
|
3462
|
+
function Mc(e, t, n, r = !0) {
|
|
3459
3463
|
if (!n || !n.clipX && !n.clipY) return {
|
|
3460
3464
|
requiresScissor: !1,
|
|
3461
3465
|
coords: t
|
|
@@ -3472,7 +3476,7 @@ function jc(e, t, n, r = !0) {
|
|
|
3472
3476
|
coords: i.flatten()
|
|
3473
3477
|
};
|
|
3474
3478
|
}
|
|
3475
|
-
function
|
|
3479
|
+
function Nc(e, t) {
|
|
3476
3480
|
let n = t?.clipX ? (t.rect.x - e.x) / e.width : 0, r = t?.clipX ? (t.rect.x2 - e.x) / e.width : 1;
|
|
3477
3481
|
return [
|
|
3478
3482
|
n,
|
|
@@ -3483,7 +3487,7 @@ function Mc(e, t) {
|
|
|
3483
3487
|
}
|
|
3484
3488
|
//#endregion
|
|
3485
3489
|
//#region ../core/src/rendering/webgl/marks/arrow.js
|
|
3486
|
-
var
|
|
3490
|
+
var Pc = Math.PI / 180, Fc = 1e-6, Ic = 1, Lc = 90, Rc = ["triangle", "open"], zc = ["inside", "outside"], Bc = class extends Ac {
|
|
3487
3491
|
getAttributes() {
|
|
3488
3492
|
return [
|
|
3489
3493
|
"uniqueId",
|
|
@@ -3511,7 +3515,7 @@ var Nc = Math.PI / 180, Pc = 1e-6, Fc = 1, Ic = 90, Lc = ["triangle", "open"], R
|
|
|
3511
3515
|
finalizeGraphicsInitialization() {
|
|
3512
3516
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
3513
3517
|
let e = this.properties;
|
|
3514
|
-
this.registerMarkUniformValue("uHeadSlope", e.headAngle,
|
|
3518
|
+
this.registerMarkUniformValue("uHeadSlope", e.headAngle, Hc), this.registerMarkUniformValue("uHeadNotchSlope", e.headNotchAngle, Hc), this.registerMarkUniformValue("uHeadShape", e.headShape, (e) => Vc(Rc, 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, Uc), this.registerMarkUniformValue("uStem", e.stem), this.registerMarkUniformValue("uHeadPlacement", e.headPlacement, (e) => Vc(zc, e));
|
|
3515
3519
|
}
|
|
3516
3520
|
updateGraphicsData(e) {
|
|
3517
3521
|
let t = e.getItemCount(), n = new hc({
|
|
@@ -3534,25 +3538,25 @@ var Nc = Math.PI / 180, Pc = 1e-6, Fc = 1, Ic = 90, Lc = ["triangle", "open"], R
|
|
|
3534
3538
|
}, e);
|
|
3535
3539
|
}
|
|
3536
3540
|
};
|
|
3537
|
-
function
|
|
3541
|
+
function Vc(e, t) {
|
|
3538
3542
|
let n = e.indexOf(t);
|
|
3539
3543
|
if (n < 0) throw Error(`Unsupported arrow mark value: ${t}`);
|
|
3540
3544
|
return n;
|
|
3541
3545
|
}
|
|
3542
|
-
function Vc(e) {
|
|
3543
|
-
return Math.max(Math.tan(Math.min(Math.max(e, Fc), Ic) * Nc), Pc);
|
|
3544
|
-
}
|
|
3545
3546
|
function Hc(e) {
|
|
3547
|
+
return Math.max(Math.tan(Math.min(Math.max(e, Ic), Lc) * Pc), Fc);
|
|
3548
|
+
}
|
|
3549
|
+
function Uc(e) {
|
|
3546
3550
|
return e ?? -1;
|
|
3547
3551
|
}
|
|
3548
3552
|
//#endregion
|
|
3549
3553
|
//#region ../core/src/rendering/webgl/marks/link.vertex.glsl
|
|
3550
|
-
var Uc = "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", Wc = "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", Gc = "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", Kc = [
|
|
3554
|
+
var Wc = "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", Gc = "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", Kc = "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 = [
|
|
3551
3555
|
"arc",
|
|
3552
3556
|
"dome",
|
|
3553
3557
|
"diagonal",
|
|
3554
3558
|
"line"
|
|
3555
|
-
],
|
|
3559
|
+
], Jc = ["vertical", "horizontal"], Yc = class extends Ac {
|
|
3556
3560
|
constructor(e, t, n) {
|
|
3557
3561
|
super(e, t, n), this._baseInstanceExt = void 0;
|
|
3558
3562
|
}
|
|
@@ -3574,12 +3578,12 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3574
3578
|
];
|
|
3575
3579
|
}
|
|
3576
3580
|
initializeGraphics() {
|
|
3577
|
-
super.initializeGraphics(), this._baseInstanceExt = this.gl.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"), this.createAndLinkShaders(
|
|
3581
|
+
super.initializeGraphics(), this._baseInstanceExt = this.gl.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"), this.createAndLinkShaders(Wc, Gc, [Kc]);
|
|
3578
3582
|
}
|
|
3579
3583
|
finalizeGraphicsInitialization() {
|
|
3580
3584
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
3581
3585
|
let e = this.properties;
|
|
3582
|
-
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) =>
|
|
3586
|
+
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) => Jc.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);
|
|
3583
3587
|
}
|
|
3584
3588
|
updateGraphicsData(e) {
|
|
3585
3589
|
let t = e.getItemCount(), n = new _c({
|
|
@@ -3610,7 +3614,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3610
3614
|
Y(t, this.programInfo, this.bufferInfo), t.drawArraysInstanced(t.TRIANGLE_STRIP, 0, n(), r);
|
|
3611
3615
|
}, e);
|
|
3612
3616
|
}
|
|
3613
|
-
},
|
|
3617
|
+
}, Xc = "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", Zc = "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", Qc = "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", $c = class extends Ac {
|
|
3614
3618
|
getAttributes() {
|
|
3615
3619
|
return [
|
|
3616
3620
|
"uniqueId",
|
|
@@ -3633,7 +3637,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3633
3637
|
];
|
|
3634
3638
|
}
|
|
3635
3639
|
initializeGraphics() {
|
|
3636
|
-
super.initializeGraphics(), this.createAndLinkShaders(
|
|
3640
|
+
super.initializeGraphics(), this.createAndLinkShaders(Xc, Zc, [Qc]);
|
|
3637
3641
|
}
|
|
3638
3642
|
finalizeGraphicsInitialization() {
|
|
3639
3643
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
@@ -3669,7 +3673,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3669
3673
|
n && oo(t, this.vertexArrayInfo, t.POINTS, n, e);
|
|
3670
3674
|
}, e);
|
|
3671
3675
|
}
|
|
3672
|
-
}, $c = "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", el = "#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", tl = "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", nl = [
|
|
3676
|
+
}, el = "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", tl = "#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", nl = "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", rl = [
|
|
3673
3677
|
"none",
|
|
3674
3678
|
"diagonal",
|
|
3675
3679
|
"antiDiagonal",
|
|
@@ -3680,7 +3684,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3680
3684
|
"dots",
|
|
3681
3685
|
"rings",
|
|
3682
3686
|
"ringsLarge"
|
|
3683
|
-
],
|
|
3687
|
+
], il = class extends Ac {
|
|
3684
3688
|
get opaque() {
|
|
3685
3689
|
return ce(this, "opaque", () => !this.#e() && !this.#t() && !this.properties.shadowOpacity && i(this.encoding.fillOpacity) && this.encoding.fillOpacity.value == 1 && this.properties.minOpacity == 1) && this.unitView.getEffectiveOpacity() == 1;
|
|
3686
3690
|
}
|
|
@@ -3714,12 +3718,12 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3714
3718
|
initializeGraphics() {
|
|
3715
3719
|
super.initializeGraphics();
|
|
3716
3720
|
let e = [];
|
|
3717
|
-
this.#e() && e.push("ROUNDED_CORNERS"), this.#t() && e.push("STROKED"), this.properties.shadowOpacity && e.push("SHADOW"), this.createAndLinkShaders(
|
|
3721
|
+
this.#e() && e.push("ROUNDED_CORNERS"), this.#t() && e.push("STROKED"), this.properties.shadowOpacity && e.push("SHADOW"), this.createAndLinkShaders(el, tl, [nl, ...e.map((e) => "#define " + e)]);
|
|
3718
3722
|
}
|
|
3719
3723
|
finalizeGraphicsInitialization() {
|
|
3720
3724
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
3721
3725
|
let e = this.properties;
|
|
3722
|
-
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,
|
|
3726
|
+
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, rl.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", Xo);
|
|
3723
3727
|
}
|
|
3724
3728
|
updateGraphicsData(e) {
|
|
3725
3729
|
let t = e.getItemCount(), n = new mc({
|
|
@@ -3741,7 +3745,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3741
3745
|
oo(t, this.vertexArrayInfo, t.TRIANGLE_STRIP, n, e);
|
|
3742
3746
|
}, e);
|
|
3743
3747
|
}
|
|
3744
|
-
},
|
|
3748
|
+
}, al = "// 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", ol = "// 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", sl = "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", cl = class extends Ac {
|
|
3745
3749
|
constructor(e, t, n) {
|
|
3746
3750
|
super(e, t, n), this.dashTexture = void 0, this.dashTextureSize = 0;
|
|
3747
3751
|
}
|
|
@@ -3764,7 +3768,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3764
3768
|
}
|
|
3765
3769
|
initializeGraphics() {
|
|
3766
3770
|
super.initializeGraphics();
|
|
3767
|
-
let e = this.gl, t =
|
|
3771
|
+
let e = this.gl, t = ll(this.properties.strokeDash);
|
|
3768
3772
|
this.dashTexture = ai(e, {
|
|
3769
3773
|
level: 0,
|
|
3770
3774
|
mag: e.NEAREST,
|
|
@@ -3773,7 +3777,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3773
3777
|
format: e.RED,
|
|
3774
3778
|
src: t,
|
|
3775
3779
|
height: 1
|
|
3776
|
-
}), this.dashTextureSize = t.length, this.createAndLinkShaders(
|
|
3780
|
+
}), this.dashTextureSize = t.length, this.createAndLinkShaders(al, ol, [sl]);
|
|
3777
3781
|
}
|
|
3778
3782
|
finalizeGraphicsInitialization() {
|
|
3779
3783
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
@@ -3806,7 +3810,7 @@ var Uc = "flat out vec4 vColor;\n\n/** Stroke width */\nflat out float vSize;\n\
|
|
|
3806
3810
|
this.dashTexture &&= (this.gl.deleteTexture(this.dashTexture), void 0), super.dispose();
|
|
3807
3811
|
}
|
|
3808
3812
|
};
|
|
3809
|
-
function
|
|
3813
|
+
function ll(e) {
|
|
3810
3814
|
if (!e) return /* @__PURE__ */ new Uint8Array();
|
|
3811
3815
|
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));
|
|
3812
3816
|
let t = e.reduce((e, t) => e + t), n = new Uint8Array(t), r = !0, i = 0;
|
|
@@ -3818,24 +3822,24 @@ function cl(e) {
|
|
|
3818
3822
|
}
|
|
3819
3823
|
//#endregion
|
|
3820
3824
|
//#region ../core/src/rendering/webgl/marks/text.vertex.glsl
|
|
3821
|
-
var
|
|
3825
|
+
var ul = "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", dl = "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", fl = "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", pl = 1024, ml = {
|
|
3822
3826
|
left: -1,
|
|
3823
3827
|
center: 0,
|
|
3824
3828
|
right: 1
|
|
3825
|
-
},
|
|
3829
|
+
}, hl = {
|
|
3826
3830
|
top: -1,
|
|
3827
3831
|
middle: 0,
|
|
3828
3832
|
bottom: 1,
|
|
3829
3833
|
alphabetic: 1,
|
|
3830
3834
|
baseline: 1
|
|
3831
|
-
},
|
|
3832
|
-
point:
|
|
3833
|
-
rect:
|
|
3834
|
-
arrow:
|
|
3835
|
-
rule:
|
|
3836
|
-
tick:
|
|
3837
|
-
link:
|
|
3838
|
-
text: class extends
|
|
3835
|
+
}, gl = {
|
|
3836
|
+
point: $c,
|
|
3837
|
+
rect: il,
|
|
3838
|
+
arrow: Bc,
|
|
3839
|
+
rule: cl,
|
|
3840
|
+
tick: cl,
|
|
3841
|
+
link: Yc,
|
|
3842
|
+
text: class extends Ac {
|
|
3839
3843
|
getAttributes() {
|
|
3840
3844
|
return [
|
|
3841
3845
|
"uniqueId",
|
|
@@ -3855,7 +3859,7 @@ var ll = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
|
|
|
3855
3859
|
];
|
|
3856
3860
|
}
|
|
3857
3861
|
initializeGraphics() {
|
|
3858
|
-
super.initializeGraphics(), this.createAndLinkShaders(
|
|
3862
|
+
super.initializeGraphics(), this.createAndLinkShaders(ul, dl, [fl]);
|
|
3859
3863
|
}
|
|
3860
3864
|
finalizeGraphicsInitialization() {
|
|
3861
3865
|
super.finalizeGraphicsInitialization(), this.gl.useProgram(this.programInfo.program);
|
|
@@ -3871,7 +3875,7 @@ var ll = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
|
|
|
3871
3875
|
e.viewportEdgeFadeDistanceBottom,
|
|
3872
3876
|
e.viewportEdgeFadeDistanceLeft
|
|
3873
3877
|
]), $a(this.markUniformInfo, {
|
|
3874
|
-
uAlign: [
|
|
3878
|
+
uAlign: [ml[e.align], hl[e.baseline]],
|
|
3875
3879
|
uD: [e.dx, -e.dy]
|
|
3876
3880
|
});
|
|
3877
3881
|
}
|
|
@@ -3895,7 +3899,7 @@ var ll = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
|
|
|
3895
3899
|
logoLetters: i
|
|
3896
3900
|
},
|
|
3897
3901
|
fontMetrics: this.font.metrics,
|
|
3898
|
-
numCharacters: Math.max(o,
|
|
3902
|
+
numCharacters: Math.max(o, pl)
|
|
3899
3903
|
});
|
|
3900
3904
|
c.addBatches(e.facetBatches);
|
|
3901
3905
|
let u = c.toArrays();
|
|
@@ -3913,12 +3917,12 @@ var ll = "in mediump vec2 vertexCoord;\nin lowp vec2 textureCoord;\n\n// Width o
|
|
|
3913
3917
|
}
|
|
3914
3918
|
}
|
|
3915
3919
|
};
|
|
3916
|
-
function
|
|
3917
|
-
let r =
|
|
3920
|
+
function _l(e, t, n) {
|
|
3921
|
+
let r = gl[e.getType()];
|
|
3918
3922
|
if (!r) throw Error("Unsupported WebGL mark type: " + e.getType());
|
|
3919
3923
|
return new r(e, t, n);
|
|
3920
3924
|
}
|
|
3921
|
-
var
|
|
3925
|
+
var vl = class {
|
|
3922
3926
|
#e = !1;
|
|
3923
3927
|
#t = /* @__PURE__ */ new Map();
|
|
3924
3928
|
#n = /* @__PURE__ */ new Map();
|
|
@@ -3928,7 +3932,7 @@ var _l = class {
|
|
|
3928
3932
|
}
|
|
3929
3933
|
#i(e) {
|
|
3930
3934
|
this.#s();
|
|
3931
|
-
let t =
|
|
3935
|
+
let t = _l(e, this.glHelper, this), n = {
|
|
3932
3936
|
mark: e,
|
|
3933
3937
|
graphics: t,
|
|
3934
3938
|
state: "compiling",
|
|
@@ -4079,9 +4083,9 @@ var _l = class {
|
|
|
4079
4083
|
};
|
|
4080
4084
|
//#endregion
|
|
4081
4085
|
//#region ../core/src/rendering/webgl/svgRasterizer.js
|
|
4082
|
-
function
|
|
4086
|
+
function yl({ runs: e, viewRoot: t, layoutResult: n, webGLHelper: r, markAdapter: i, logicalWidth: a, logicalHeight: o, pixelRatio: s }) {
|
|
4083
4087
|
let c = r.gl, l = Math.ceil(a * s), u = Math.ceil(o * s);
|
|
4084
|
-
|
|
4088
|
+
bl(c, l, u);
|
|
4085
4089
|
let d = s == 1 && n ? n : Se(t, be.create(0, 0, a, o), {
|
|
4086
4090
|
devicePixelRatio: s,
|
|
4087
4091
|
renderingOptions: { firstFacet: !0 }
|
|
@@ -4116,14 +4120,14 @@ function vl({ runs: e, viewRoot: t, layoutResult: n, webGLHelper: r, markAdapter
|
|
|
4116
4120
|
c.bindFramebuffer(c.FRAMEBUFFER, null), c.deleteTexture(f.attachments[0]), c.deleteFramebuffer(f.framebuffer);
|
|
4117
4121
|
}
|
|
4118
4122
|
}
|
|
4119
|
-
function
|
|
4123
|
+
function bl(e, t, n) {
|
|
4120
4124
|
let r = e.getParameter(e.MAX_RENDERBUFFER_SIZE), i = e.getParameter(e.MAX_TEXTURE_SIZE), a = Math.min(r, i);
|
|
4121
4125
|
if (t <= 0 || n <= 0 || t > a || n > a) throw RangeError(`SVG raster dimensions ${t} x ${n} exceed the WebGL limit ${a}.`);
|
|
4122
4126
|
}
|
|
4123
4127
|
//#endregion
|
|
4124
4128
|
//#region ../core/src/rendering/webgl/index.js
|
|
4125
|
-
function
|
|
4126
|
-
let t = new Vs(e.container, e.sizeSource, { powerPreference: e.powerPreference }, e.onCanvasResize), n = new
|
|
4129
|
+
function xl(e) {
|
|
4130
|
+
let t = new Vs(e.container, e.sizeSource, { powerPreference: e.powerPreference }, e.onCanvasResize), n = new vl(t);
|
|
4127
4131
|
return {
|
|
4128
4132
|
surface: t,
|
|
4129
4133
|
defaultFontBitmapUrl: Oe,
|
|
@@ -4144,7 +4148,7 @@ function bl(e) {
|
|
|
4144
4148
|
glHelper: t,
|
|
4145
4149
|
markAdapter: n
|
|
4146
4150
|
}),
|
|
4147
|
-
rasterizeSvgRuns: (e) =>
|
|
4151
|
+
rasterizeSvgRuns: (e) => yl({
|
|
4148
4152
|
...e,
|
|
4149
4153
|
webGLHelper: t,
|
|
4150
4154
|
markAdapter: n
|
|
@@ -4156,4 +4160,4 @@ function bl(e) {
|
|
|
4156
4160
|
};
|
|
4157
4161
|
}
|
|
4158
4162
|
//#endregion
|
|
4159
|
-
export {
|
|
4163
|
+
export { xl as createWebGLRenderingBackend };
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"homepage": "https://genomespy.app/",
|
|
11
|
-
"version": "0.88.
|
|
11
|
+
"version": "0.88.1",
|
|
12
12
|
"main": "dist/index.js",
|
|
13
13
|
"module": "dist/index.es.js",
|
|
14
14
|
"type": "module",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
|
72
72
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
|
73
73
|
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
|
74
|
-
"@genome-spy/core": "^0.88.
|
|
74
|
+
"@genome-spy/core": "^0.88.1",
|
|
75
75
|
"@reduxjs/toolkit": "^2.11.0",
|
|
76
76
|
"d3-color": "^3.1.0",
|
|
77
77
|
"idb": "^7.1.1",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"zarrita": "^0.6.1"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"@genome-spy/app-agent": "^0.88.
|
|
88
|
-
"@genome-spy/inspector": "^0.88.
|
|
87
|
+
"@genome-spy/app-agent": "^0.88.1",
|
|
88
|
+
"@genome-spy/inspector": "^0.88.1"
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "e0e01085f8f92e5da31120268f4b157be1666523"
|
|
91
91
|
}
|