@genome-spy/core 0.62.2 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/bundle/index.es.js +4052 -3992
  2. package/dist/bundle/index.js +97 -97
  3. package/dist/src/genomeSpy.d.ts +11 -0
  4. package/dist/src/genomeSpy.d.ts.map +1 -1
  5. package/dist/src/genomeSpy.js +98 -20
  6. package/dist/src/gl/includes/common.glsl.js +1 -1
  7. package/dist/src/gl/webGLHelper.d.ts +18 -14
  8. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  9. package/dist/src/gl/webGLHelper.js +58 -65
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/index.js +1 -0
  12. package/dist/src/marks/mark.d.ts +6 -1
  13. package/dist/src/marks/mark.d.ts.map +1 -1
  14. package/dist/src/marks/mark.js +10 -16
  15. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  16. package/dist/src/marks/text.d.ts.map +1 -1
  17. package/dist/src/marks/text.js +7 -15
  18. package/dist/src/marks/text.vertex.glsl.js +1 -1
  19. package/dist/src/types/embedApi.d.ts +16 -0
  20. package/dist/src/types/viewContext.d.ts +0 -2
  21. package/dist/src/view/gridView/gridView.js +1 -1
  22. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts +32 -17
  23. package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
  24. package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +85 -39
  25. package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -1
  26. package/dist/src/view/renderingContext/simpleViewRenderingContext.js +5 -1
  27. package/dist/src/view/renderingContext/viewRenderingContext.d.ts +1 -0
  28. package/dist/src/view/renderingContext/viewRenderingContext.d.ts.map +1 -1
  29. package/dist/src/view/renderingContext/viewRenderingContext.js +4 -0
  30. package/package.json +2 -2
@@ -171,21 +171,11 @@ export default class TextMark extends Mark {
171
171
 
172
172
  const props = this.properties;
173
173
 
174
- this.registerMarkUniformValue(
175
- "uSdfNumerator",
176
- /** @type {import("../spec/parameter.js").ExprRef | number} */
177
- ({ expr: "devicePixelRatio" }),
178
- (dpr) => {
179
- let q = 0.35; // TODO: Ensure that this makes sense. Now chosen by trial & error
180
- if (this.properties.logoLetters) {
181
- // Adjust to make stretched letters a bit less blurry
182
- // A proper solution would probably be to compute gradients in the fragment shader
183
- // to find a suitable divisor.
184
- q /= 2;
185
- }
186
- return this.font.metrics.common.base / (dpr / q);
187
- }
188
- );
174
+ // 0.35 is a magic number found by trial and error
175
+ const sdfNumerator =
176
+ this.font.metrics.common.base *
177
+ 0.35 *
178
+ (this.properties.logoLetters ? 0.5 : 1);
189
179
 
190
180
  this.registerMarkUniformValue("uPaddingX", props.paddingX);
191
181
  this.registerMarkUniformValue("uPaddingY", props.paddingY);
@@ -200,6 +190,8 @@ export default class TextMark extends Mark {
200
190
 
201
191
  uLogoLetter: !!props.logoLetters,
202
192
 
193
+ uSdfNumerator: sdfNumerator,
194
+
203
195
  uViewportEdgeFadeWidth: [
204
196
  props.viewportEdgeFadeWidthTop,
205
197
  props.viewportEdgeFadeWidthRight,
@@ -1,2 +1,2 @@
1
- const shader = "in mediump vec2 vertexCoord;in lowp vec2 textureCoord;in float width;out vec2 vTexCoord;out vec4 vColor;out float vSlope;out float vEdgeFadeOpacity;out float vGamma;struct RangeResult{float pos;float scale;};float minValue(vec4 v){return min(min(v.x,v.y),min(v.z,v.w));}float maxValue(vec4 v){return max(max(v.x,v.y),max(v.z,v.w));}/***All measures are in[0,1]*/RangeResult positionInsideRange(float a,float b,float width,float padding,int align,bool flush){float span=b-a;float paddedWidth=width+2.0*padding;if(a>1.0||b<0.0){return RangeResult(0.0,0.0);}float extra=max(0.0,span-paddedWidth);float pos;if(align==0){float centre=a+b;if(flush){float leftOver=max(0.0,paddedWidth-centre);centre+=min(leftOver,extra);float rightOver=max(0.0,paddedWidth+centre-2.0);centre-=min(rightOver,extra);}pos=centre/2.0;}else if(align<0){float edge=a;if(flush){float over=max(0.0,-edge);edge+=min(over,extra);}pos=edge+padding;}else{float edge=b;if(flush){float over=max(0.0,edge-1.0);edge-=min(over,extra);}pos=edge-padding;}float scale=clamp((span-padding)/paddedWidth,0.0,1.0);return RangeResult(pos,scale);}vec2 calculateRotatedDimensions(float width,mat2 rotationMatrix){vec2 a=abs(rotationMatrix*vec2(width/2.0,0.5));vec2 b=abs(rotationMatrix*vec2(width/2.0,-0.5));return vec2(max(a.x,b.x),max(a.y,b.y))*2.0;}ivec2 fixAlignForAngle(ivec2 align,float angleInDegrees){float a=mod(angleInDegrees+45.0,360.0);int x=align.x;int y=-align.y;if(a<90.0){return ivec2(x,y);}else if(a<180.0){return ivec2(y,-x);}else if(a<270.0){return ivec2(-x,y);}else{return ivec2(-y,x);}}void main(void){float opacity=getScaled_opacity()*uViewOpacity;vec2 size=vec2(getScaled_size());float x=getScaled_x();float y=getScaled_y();float scale=1.0;float angleInDegrees=getScaled_angle();float angle=-angleInDegrees*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);mat2 rotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);vec2 flushSize=calculateRotatedDimensions(width,rotationMatrix);\n#if defined(x2_DEFINED) || defined(y2_DEFINED)\nivec2 align=fixAlignForAngle(uAlign,angleInDegrees);\n#else\nivec2 align=uAlign;\n#endif\n#ifdef x2_DEFINED\nfloat x2=getScaled_x2();if(uLogoLetter){size.x=(x2-x)*uViewportSize.x;x+=(x2-x)/2.0;}else{float x2=getScaled_x2();RangeResult result=positionInsideRange(min(x,x2),max(x,x2),size.x*scale*flushSize.x/uViewportSize.x,uPaddingX/uViewportSize.x,align.x,uFlushX);x=result.pos;scale*=result.scale;}\n#endif\nvec2 pos=applySampleFacet(vec2(x,y));\n#ifdef y2_DEFINED\nfloat y2=getScaled_y2();vec2 pos2=applySampleFacet(vec2(x,y2));if(uLogoLetter){size.y=(pos2.y-pos.y)*uViewportSize.y;pos.y+=(pos2.y-pos.y)/2.0;}else{RangeResult result=positionInsideRange(min(pos.y,pos2.y),max(pos.y,pos2.y),size.y*scale*flushSize.y/uViewportSize.y,uPaddingY/uViewportSize.y,align.y,uFlushY);pos.y=result.pos;scale*=result.scale;}\n#endif\nif(scale<1.0){if(uSqueeze){vec2 scaleFadeExtent=vec2(3.0,6.0)/size;if(scale<scaleFadeExtent[0]){gl_Position=vec4(0.0);return;}size*=scale;opacity*=linearstep(scaleFadeExtent[0],scaleFadeExtent[1],scale);}else if(scale<1.0){gl_Position=vec4(0.0);return;}}vec2 charPos=rotationMatrix*(vertexCoord*size+uD);vec2 unitPos=pos+charPos/uViewportSize;gl_Position=unitToNdc(unitPos);vSlope=max(1.0,min(size.x,size.y)/uSdfNumerator);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vGamma=getGammaForColor(color);vTexCoord=textureCoord;if(maxValue(uViewportEdgeFadeDistance)>-pow(10.0,10.0)){vEdgeFadeOpacity=minValue(((vec4(1.0,1.0,0.0,0.0)+vec4(-1.0,-1.0,1.0,1.0)*unitPos.yxyx)*uViewportSize.yxyx-uViewportEdgeFadeDistance)/uViewportEdgeFadeWidth);}else{vEdgeFadeOpacity=1.0;}setupPicking();}";
1
+ const shader = "in mediump vec2 vertexCoord;in lowp vec2 textureCoord;in float width;out vec2 vTexCoord;out vec4 vColor;out float vSlope;out float vEdgeFadeOpacity;out float vGamma;struct RangeResult{float pos;float scale;};float minValue(vec4 v){return min(min(v.x,v.y),min(v.z,v.w));}float maxValue(vec4 v){return max(max(v.x,v.y),max(v.z,v.w));}/***All measures are in[0,1]*/RangeResult positionInsideRange(float a,float b,float width,float padding,int align,bool flush){float span=b-a;float paddedWidth=width+2.0*padding;if(a>1.0||b<0.0){return RangeResult(0.0,0.0);}float extra=max(0.0,span-paddedWidth);float pos;if(align==0){float centre=a+b;if(flush){float leftOver=max(0.0,paddedWidth-centre);centre+=min(leftOver,extra);float rightOver=max(0.0,paddedWidth+centre-2.0);centre-=min(rightOver,extra);}pos=centre/2.0;}else if(align<0){float edge=a;if(flush){float over=max(0.0,-edge);edge+=min(over,extra);}pos=edge+padding;}else{float edge=b;if(flush){float over=max(0.0,edge-1.0);edge-=min(over,extra);}pos=edge-padding;}float scale=clamp((span-padding)/paddedWidth,0.0,1.0);return RangeResult(pos,scale);}vec2 calculateRotatedDimensions(float width,mat2 rotationMatrix){vec2 a=abs(rotationMatrix*vec2(width/2.0,0.5));vec2 b=abs(rotationMatrix*vec2(width/2.0,-0.5));return vec2(max(a.x,b.x),max(a.y,b.y))*2.0;}ivec2 fixAlignForAngle(ivec2 align,float angleInDegrees){float a=mod(angleInDegrees+45.0,360.0);int x=align.x;int y=-align.y;if(a<90.0){return ivec2(x,y);}else if(a<180.0){return ivec2(y,-x);}else if(a<270.0){return ivec2(-x,y);}else{return ivec2(-y,x);}}void main(void){float opacity=getScaled_opacity()*uViewOpacity;vec2 size=vec2(getScaled_size());float x=getScaled_x();float y=getScaled_y();float scale=1.0;float angleInDegrees=getScaled_angle();float angle=-angleInDegrees*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);mat2 rotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);vec2 flushSize=calculateRotatedDimensions(width,rotationMatrix);\n#if defined(x2_DEFINED) || defined(y2_DEFINED)\nivec2 align=fixAlignForAngle(uAlign,angleInDegrees);\n#else\nivec2 align=uAlign;\n#endif\n#ifdef x2_DEFINED\nfloat x2=getScaled_x2();if(uLogoLetter){size.x=(x2-x)*uViewportSize.x;x+=(x2-x)/2.0;}else{float x2=getScaled_x2();RangeResult result=positionInsideRange(min(x,x2),max(x,x2),size.x*scale*flushSize.x/uViewportSize.x,uPaddingX/uViewportSize.x,align.x,uFlushX);x=result.pos;scale*=result.scale;}\n#endif\nvec2 pos=applySampleFacet(vec2(x,y));\n#ifdef y2_DEFINED\nfloat y2=getScaled_y2();vec2 pos2=applySampleFacet(vec2(x,y2));if(uLogoLetter){size.y=(pos2.y-pos.y)*uViewportSize.y;pos.y+=(pos2.y-pos.y)/2.0;}else{RangeResult result=positionInsideRange(min(pos.y,pos2.y),max(pos.y,pos2.y),size.y*scale*flushSize.y/uViewportSize.y,uPaddingY/uViewportSize.y,align.y,uFlushY);pos.y=result.pos;scale*=result.scale;}\n#endif\nif(scale<1.0){if(uSqueeze){vec2 scaleFadeExtent=vec2(3.0,6.0)/size;if(scale<scaleFadeExtent[0]){gl_Position=vec4(0.0);return;}size*=scale;opacity*=linearstep(scaleFadeExtent[0],scaleFadeExtent[1],scale);}else if(scale<1.0){gl_Position=vec4(0.0);return;}}vec2 charPos=rotationMatrix*(vertexCoord*size+uD);vec2 unitPos=pos+charPos/uViewportSize;gl_Position=unitToNdc(unitPos);vSlope=max(1.0,min(size.x,size.y)/uSdfNumerator*uDevicePixelRatio);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vGamma=getGammaForColor(color);vTexCoord=textureCoord;if(maxValue(uViewportEdgeFadeDistance)>-pow(10.0,10.0)){vEdgeFadeOpacity=minValue(((vec4(1.0,1.0,0.0,0.0)+vec4(-1.0,-1.0,1.0,1.0)*unitPos.yxyx)*uViewportSize.yxyx-uViewportEdgeFadeDistance)/uViewportEdgeFadeWidth);}else{vEdgeFadeOpacity=1.0;}setupPicking();}";
2
2
  export default shader;
@@ -77,4 +77,20 @@ export interface EmbedResult {
77
77
  * @param data new data. If left undefined, the data is retrieved from a provider.
78
78
  */
79
79
  updateNamedData: (name: string, data?: any[]) => void;
80
+
81
+ /**
82
+ * Returns a PNG data URL of the current canvas.
83
+ *
84
+ * @param {number} [logicalWidth] Custom width, defaults to canvas width
85
+ * @param {number} [logicalHeight] Custom height, defaults to canvas height
86
+ * @param {number} [devicePixelRatio] Defaults to window.devicePixelRatio
87
+ * @param {string} [clearColor] Background color. A CSS color, null for transparent
88
+ * @returns A PNG data URL
89
+ */
90
+ exportCanvas: (
91
+ logicalWidth: number,
92
+ logicalHeight: number,
93
+ devicePixelRatio: number,
94
+ clearColor: string
95
+ ) => string;
80
96
  }
@@ -28,8 +28,6 @@ export default interface ViewContext {
28
28
  genomeStore?: GenomeStore;
29
29
  fontManager: BmFontManager;
30
30
 
31
- devicePixelRatio: number;
32
-
33
31
  requestLayoutReflow: () => void;
34
32
 
35
33
  updateTooltip: <T>(
@@ -449,7 +449,7 @@ export default class GridView extends ContainerView {
449
449
  context.pushView(this, coords);
450
450
 
451
451
  const flexOpts = {
452
- devicePixelRatio: this.context.devicePixelRatio,
452
+ devicePixelRatio: context.getDevicePixelRatio(),
453
453
  };
454
454
  const columnFlexCoords = mapToPixelCoords(
455
455
  this.#makeFlexItems("column"),
@@ -1,30 +1,45 @@
1
+ /**
2
+ * @typedef {object} BufferedViewRenderingOptions
3
+ * @prop {import("../../gl/webGLHelper.js").default} webGLHelper
4
+ * @prop {{width: number, height: number}} canvasSize Size of the canvas in logical pixels.
5
+ * @prop {number} devicePixelRatio
6
+ * @prop {import("twgl.js").FramebufferInfo} [framebufferInfo]
7
+ * @prop {string} [clearColor] Clear color for the WebGL context,
8
+ * defaults to transparent black.
9
+ */
10
+ /**
11
+ * View rendering context that buffers the actual WebGL rendering for
12
+ * efficient animation.
13
+ */
1
14
  export default class BufferedViewRenderingContext extends ViewRenderingContext {
2
15
  /**
3
16
  * @param {import("../../types/rendering.js").GlobalRenderingOptions} globalOptions
4
- * @param {import("../../gl/webGLHelper.js").default} webGLHelper
17
+ * @param {BufferedViewRenderingOptions} bufferedOptions
5
18
  */
6
- constructor(globalOptions: import("../../types/rendering.js").GlobalRenderingOptions, webGLHelper: import("../../gl/webGLHelper.js").default);
7
- webGLHelper: import("../../gl/webGLHelper.js").default;
8
- /**
9
- * @type {import("../../types/rendering.js").BufferedRenderingRequest[]}
10
- */
11
- buffer: import("../../types/rendering.js").BufferedRenderingRequest[];
12
- /** @type {import("../layout/rectangle.js").default} */
13
- coords: import("../layout/rectangle.js").default;
14
- /** @type {Set<import("../view.js").default>} */
15
- views: Set<import("../view.js").default>;
19
+ constructor(globalOptions: import("../../types/rendering.js").GlobalRenderingOptions, bufferedOptions: BufferedViewRenderingOptions);
16
20
  /**
17
21
  * Renders marks in an optimized order, minimizing the number of WebGL state
18
22
  * changes.
19
23
  */
20
24
  render(): void;
21
- _buildBatch(): void;
25
+ #private;
26
+ }
27
+ export type BufferedViewRenderingOptions = {
28
+ webGLHelper: import("../../gl/webGLHelper.js").default;
22
29
  /**
23
- * Store the operations as a sequence of commands for cheap subsequent rendering.
24
- *
25
- * @type {(function():void)[]}
30
+ * Size of the canvas in logical pixels.
26
31
  */
27
- batch: (() => void)[];
28
- }
32
+ canvasSize: {
33
+ width: number;
34
+ height: number;
35
+ };
36
+ devicePixelRatio: number;
37
+ framebufferInfo?: import("twgl.js").FramebufferInfo;
38
+ /**
39
+ * Clear color for the WebGL context,
40
+ * defaults to transparent black.
41
+ */
42
+ clearColor?: string;
43
+ };
29
44
  import ViewRenderingContext from "./viewRenderingContext.js";
30
45
  //# sourceMappingURL=bufferedViewRenderingContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bufferedViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/bufferedViewRenderingContext.js"],"names":[],"mappings":"AAIA;IACI;;;OAGG;IACH,2BAHW,OAAO,0BAA0B,EAAE,sBAAsB,eACzD,OAAO,yBAAyB,EAAE,OAAO,EAiBnD;IAZG,uDAA8B;IAE9B;;OAEG;IACH,QAFU,OAAO,0BAA0B,EAAE,wBAAwB,EAAE,CAEvD;IAEhB,uDAAuD;IACvD,QADW,OAAO,wBAAwB,EAAE,OAAO,CAC5B;IAEvB,gDAAgD;IAChD,OADW,GAAG,CAAC,OAAO,YAAY,EAAE,OAAO,CAAC,CACtB;IAsC1B;;;OAGG;IACH,eA+BC;IAED,oBA2EC;IA1EG;;;;OAIG;IACH,OAFU,CAAC,MAAW,IAAI,CAAC,EAAE,CAEd;CAsEtB;iCA5KgC,2BAA2B"}
1
+ {"version":3,"file":"bufferedViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/bufferedViewRenderingContext.js"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AAEH;;;GAGG;AACH;IA2BI;;;OAGG;IACH,2BAHW,OAAO,0BAA0B,EAAE,sBAAsB,mBACzD,4BAA4B,EActC;IAyCD;;;OAGG;IACH,eAmCC;;CA8EJ;;iBArNS,OAAO,yBAAyB,EAAE,OAAO;;;;gBACzC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC;sBAC/B,MAAM;sBACN,OAAO,SAAS,EAAE,eAAe;;;;;iBACjC,MAAM;;iCATiB,2BAA2B"}
@@ -1,27 +1,69 @@
1
1
  import { group } from "d3-array";
2
2
 
3
3
  import ViewRenderingContext from "./viewRenderingContext.js";
4
-
4
+ import { color } from "d3-color";
5
+
6
+ /**
7
+ * @typedef {object} BufferedViewRenderingOptions
8
+ * @prop {import("../../gl/webGLHelper.js").default} webGLHelper
9
+ * @prop {{width: number, height: number}} canvasSize Size of the canvas in logical pixels.
10
+ * @prop {number} devicePixelRatio
11
+ * @prop {import("twgl.js").FramebufferInfo} [framebufferInfo]
12
+ * @prop {string} [clearColor] Clear color for the WebGL context,
13
+ * defaults to transparent black.
14
+ */
15
+
16
+ /**
17
+ * View rendering context that buffers the actual WebGL rendering for
18
+ * efficient animation.
19
+ */
5
20
  export default class BufferedViewRenderingContext extends ViewRenderingContext {
21
+ /** @type {[number, number, number, number]} */
22
+ #clearColor = [0, 0, 0, 0];
23
+
24
+ /** @type {(() => void)[]} */
25
+ #batch;
26
+
27
+ /**
28
+ * @type {import("../../types/rendering.js").BufferedRenderingRequest[]}
29
+ */
30
+ #buffer = [];
31
+
32
+ /** @type {import("twgl.js").FramebufferInfo} */
33
+ #framebufferInfo;
34
+
35
+ /** @type {import("../../gl/webGLHelper.js").default} */
36
+ #webGLHelper;
37
+
38
+ /** @type {Set<import("../view.js").default>} */
39
+ #views = new Set();
40
+
41
+ /** @type {import("../layout/rectangle.js").default} */
42
+ #coords = undefined;
43
+
44
+ #dpr = 1;
45
+ #canvasSize = { width: 0, height: 0 };
46
+
6
47
  /**
7
48
  * @param {import("../../types/rendering.js").GlobalRenderingOptions} globalOptions
8
- * @param {import("../../gl/webGLHelper.js").default} webGLHelper
49
+ * @param {BufferedViewRenderingOptions} bufferedOptions
9
50
  */
10
- constructor(globalOptions, webGLHelper) {
51
+ constructor(globalOptions, bufferedOptions) {
11
52
  super(globalOptions);
12
53
 
13
- this.webGLHelper = webGLHelper;
14
-
15
- /**
16
- * @type {import("../../types/rendering.js").BufferedRenderingRequest[]}
17
- */
18
- this.buffer = [];
54
+ this.#webGLHelper = bufferedOptions.webGLHelper;
55
+ this.#framebufferInfo = bufferedOptions.framebufferInfo;
56
+ this.#dpr = bufferedOptions.devicePixelRatio;
57
+ this.#canvasSize = bufferedOptions.canvasSize;
19
58
 
20
- /** @type {import("../layout/rectangle.js").default} */
21
- this.coords = undefined;
59
+ if (bufferedOptions.clearColor) {
60
+ const c = color(bufferedOptions.clearColor).rgb();
61
+ this.#clearColor = [c.r / 255, c.g / 255, c.b / 255, c.opacity];
62
+ }
63
+ }
22
64
 
23
- /** @type {Set<import("../view.js").default>} */
24
- this.views = new Set();
65
+ getDevicePixelRatio() {
66
+ return this.#dpr;
25
67
  }
26
68
 
27
69
  /**
@@ -33,8 +75,8 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
33
75
  * @override
34
76
  */
35
77
  pushView(view, coords) {
36
- this.views.add(view);
37
- this.coords = coords;
78
+ this.#views.add(view);
79
+ this.#coords = coords;
38
80
  }
39
81
 
40
82
  /**
@@ -50,10 +92,10 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
50
92
 
51
93
  const callback = mark.render(options);
52
94
  if (callback) {
53
- this.buffer.push({
95
+ this.#buffer.push({
54
96
  mark,
55
97
  callback,
56
- coords: this.coords,
98
+ coords: this.#coords,
57
99
  clipRect: options.clipRect,
58
100
  });
59
101
  }
@@ -64,45 +106,47 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
64
106
  * changes.
65
107
  */
66
108
  render() {
67
- if (!this.batch) {
68
- this._buildBatch();
109
+ if (!this.#batch) {
110
+ this.#buildBatch();
69
111
  }
70
112
 
71
- if (this.batch.length == 0) {
113
+ if (this.#batch.length == 0) {
72
114
  return;
73
115
  }
74
116
 
75
- const gl = this.webGLHelper.gl;
76
- const picking = this.globalOptions.picking;
117
+ const gl = this.#webGLHelper.gl;
118
+ const fbi = this.#framebufferInfo;
77
119
 
78
- gl.bindFramebuffer(
79
- gl.FRAMEBUFFER,
80
- picking ? this.webGLHelper._pickingBufferInfo.framebuffer : null
81
- );
120
+ if (fbi) {
121
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fbi.framebuffer);
122
+ gl.viewport(0, 0, fbi.width, fbi.height);
123
+ } else {
124
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
125
+ }
82
126
 
83
- this.webGLHelper.clearAll();
127
+ gl.disable(gl.SCISSOR_TEST);
128
+ gl.clearColor(...this.#clearColor);
129
+ gl.clear(gl.COLOR_BUFFER_BIT);
84
130
 
85
- for (const view of this.views) {
131
+ for (const view of this.#views) {
86
132
  view.onBeforeRender();
87
133
  }
88
134
 
89
135
  // Execute the batch
90
- for (const op of this.batch) {
136
+ for (const op of this.#batch) {
91
137
  op();
92
138
  }
93
139
 
94
- if (picking) {
140
+ if (this.#framebufferInfo) {
95
141
  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
96
142
  }
97
143
  }
98
144
 
99
- _buildBatch() {
145
+ #buildBatch() {
100
146
  /**
101
147
  * Store the operations as a sequence of commands for cheap subsequent rendering.
102
- *
103
- * @type {(function():void)[]}
104
148
  */
105
- this.batch = [];
149
+ this.#batch = [];
106
150
 
107
151
  /**
108
152
  * Is drawing enabled or not. As an optimization this is toggled off for invisible views.
@@ -129,7 +173,7 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
129
173
  // Note: by reversing the buffer, we ensure ensure that the last instance
130
174
  // of a mark determines the order of the groups.
131
175
  const requestByMark = group(
132
- this.buffer.reverse(),
176
+ this.#buffer.reverse(),
133
177
  (request) => request.mark
134
178
  );
135
179
 
@@ -140,11 +184,11 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
140
184
  }
141
185
 
142
186
  // eslint-disable-next-line no-loop-func
143
- this.batch.push(() => {
187
+ this.#batch.push(() => {
144
188
  enabled = mark.unitView.getEffectiveOpacity() > 0;
145
189
  });
146
190
  // Change program, set common uniforms (mark properties, shared domains)
147
- this.batch.push(
191
+ this.#batch.push(
148
192
  ...mark
149
193
  .prepareRender(this.globalOptions)
150
194
  .map((op) => ifEnabled(op))
@@ -156,18 +200,20 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
156
200
  const coords = request.coords;
157
201
  // Render each facet
158
202
  if (!coords.equals(previousCoords)) {
159
- this.batch.push(
203
+ this.#batch.push(
160
204
  // eslint-disable-next-line no-loop-func
161
205
  ifEnabled(() => {
162
206
  // Suppress rendering if viewport is outside the clipRect
163
207
  viewportVisible = mark.setViewport(
208
+ this.#canvasSize,
209
+ this.#dpr,
164
210
  coords,
165
211
  request.clipRect
166
212
  );
167
213
  })
168
214
  );
169
215
  }
170
- this.batch.push(ifEnabledAndVisible(request.callback));
216
+ this.#batch.push(ifEnabledAndVisible(request.callback));
171
217
  previousCoords = request.coords;
172
218
  }
173
219
  }
@@ -1 +1 @@
1
- {"version":3,"file":"simpleViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/simpleViewRenderingContext.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH;IAMQ,uDAAuD;IACvD,QADW,OAAO,wBAAwB,EAAE,OAAO,CAC5B;IAEvB,gDAAgD;IAChD,OADW,GAAG,CAAC,OAAO,YAAY,EAAE,OAAO,CAAC,CACtB;CA6C7B;;;;;mBAzDY,OAAO,YAAY,EAAE,OAAO;iCANR,2BAA2B"}
1
+ {"version":3,"file":"simpleViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/simpleViewRenderingContext.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH;IAMQ,uDAAuD;IACvD,QADW,OAAO,wBAAwB,EAAE,OAAO,CAC5B;IAEvB,gDAAgD;IAChD,OADW,GAAG,CAAC,OAAO,YAAY,EAAE,OAAO,CAAC,CACtB;CAiD7B;;;;;mBA7DY,OAAO,YAAY,EAAE,OAAO;iCANR,2BAA2B"}
@@ -58,7 +58,11 @@ export default class SimpleViewRenderingContext extends ViewRenderingContext {
58
58
  for (const op of mark.prepareRender(this.globalOptions)) {
59
59
  op();
60
60
  }
61
- mark.setViewport(this.coords, options.clipRect);
61
+
62
+ const canvasSize = { width: 100, height: 100 }; // Placeholder, should be replaced with actual canvas size
63
+ const dpr = this.getDevicePixelRatio();
64
+
65
+ mark.setViewport(canvasSize, dpr, this.coords, options.clipRect);
62
66
  mark.render(options)();
63
67
  }
64
68
  }
@@ -28,6 +28,7 @@ export default class ViewRenderingContext {
28
28
  * @param {import("../../types/rendering.js").RenderingOptions} options
29
29
  */
30
30
  renderMark(mark: import("../../marks/mark.js").default, options: import("../../types/rendering.js").RenderingOptions): void;
31
+ getDevicePixelRatio(): number;
31
32
  }
32
33
  export type View = import("../view.js").default;
33
34
  //# sourceMappingURL=viewRenderingContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"viewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/viewRenderingContext.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFW,OAAO,0BAA0B,EAAE,sBAAsB,EAInE;IADG,yEAAkC;IAGtC;;;;;;OAMG;IACH,eAJW,IAAI,UACJ,OAAO,wBAAwB,EAAE,OAAO,QAKlD;IAED;;;;OAIG;IACH,cAFW,IAAI,QAId;IAED;;;;OAIG;IACH,iBAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,0BAA0B,EAAE,gBAAgB,QAI7D;CACJ;mBAvCY,OAAO,YAAY,EAAE,OAAO"}
1
+ {"version":3,"file":"viewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/viewRenderingContext.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFW,OAAO,0BAA0B,EAAE,sBAAsB,EAInE;IADG,yEAAkC;IAGtC;;;;;;OAMG;IACH,eAJW,IAAI,UACJ,OAAO,wBAAwB,EAAE,OAAO,QAKlD;IAED;;;;OAIG;IACH,cAFW,IAAI,QAId;IAED;;;;OAIG;IACH,iBAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,0BAA0B,EAAE,gBAAgB,QAI7D;IAED,8BAEC;CACJ;mBA3CY,OAAO,YAAY,EAAE,OAAO"}
@@ -38,4 +38,8 @@ export default class ViewRenderingContext {
38
38
  renderMark(mark, options) {
39
39
  //
40
40
  }
41
+
42
+ getDevicePixelRatio() {
43
+ return 1;
44
+ }
41
45
  }
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "MIT",
10
- "version": "0.62.2",
10
+ "version": "0.63.0",
11
11
  "jsdelivr": "dist/bundle/index.js",
12
12
  "unpkg": "dist/bundle/index.js",
13
13
  "browser": "dist/bundle/index.js",
@@ -67,5 +67,5 @@
67
67
  "devDependencies": {
68
68
  "@types/long": "^4.0.1"
69
69
  },
70
- "gitHead": "74d02e7425143681fec5fda16d539d94bfdfe034"
70
+ "gitHead": "61b7ba62f15827e617d5e8321e532e4c3a2efd75"
71
71
  }