figureone 1.8.0 → 1.9.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.
package/index.js CHANGED
@@ -7174,6 +7174,11 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7174
7174
  // is precomputed so the draw loop allocates nothing). A mask with an empty
7175
7175
  // src is a transparent placeholder - an index-preserving no-op slot.
7176
7176
 
7177
+ // The webgl texture id this object currently holds a base-texture reference to
7178
+ // (acquired by initTexture, or adopted from a shared atlas via
7179
+ // setBaseTextureRef). resetTextureBuffer releases exactly this id, so the
7180
+ // release can never be unbalanced with the acquire. null = no reference held.
7181
+
7177
7182
  function GLObject(webgl) {
7178
7183
  var _this;
7179
7184
  var vertexShader = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
@@ -7203,6 +7208,7 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7203
7208
  _this.numVertices = 0;
7204
7209
  _this.uniforms = {};
7205
7210
  _this.texture = null;
7211
+ _this.acquiredBaseTextureId = null;
7206
7212
  _this.maskTextures = [];
7207
7213
  // this.selectorProgramIndex = this.webgl.getProgram(selectorVertexShader, selectorFragShader);
7208
7214
  _this.initProgram();
@@ -7463,6 +7469,10 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7463
7469
  // gl.STATIC_DRAW,
7464
7470
  // );
7465
7471
  webgl.addTexture(id, data || src, loadColor, repeat, this.executeOnLoad.bind(this), force);
7472
+ // addTexture took/holds a reference to this id; record it so
7473
+ // resetTextureBuffer releases exactly what was acquired. (For a forced
7474
+ // update the id is unchanged, so this is idempotent.)
7475
+ this.acquiredBaseTextureId = id;
7466
7476
  this.state = webgl.textures[texture.id].state;
7467
7477
 
7468
7478
  // Register the optional mask textures (textureMap color mode). Each loads
@@ -7527,6 +7537,30 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7527
7537
  // }
7528
7538
  }
7529
7539
 
7540
+ /**
7541
+ * Adopt a base-texture reference to an already-registered texture (e.g. a
7542
+ * shared font atlas uploaded by the Atlas, whose id this object renders with
7543
+ * but does not upload itself).
7544
+ *
7545
+ * Releases any previously-held base reference first (so a font/atlas change
7546
+ * rebalances correctly) and is idempotent when the id is unchanged. If the
7547
+ * texture isn't registered yet, no reference is taken and acquiredBaseTextureId
7548
+ * is cleared, so the later resetTextureBuffer release stays balanced (it only
7549
+ * releases a reference that was actually acquired).
7550
+ */
7551
+ }, {
7552
+ key: "setBaseTextureRef",
7553
+ value: function setBaseTextureRef(id) {
7554
+ if (this.acquiredBaseTextureId === id) {
7555
+ return;
7556
+ }
7557
+ var webgl = this.webgl;
7558
+ if (this.acquiredBaseTextureId != null) {
7559
+ webgl.deleteTexture(this.acquiredBaseTextureId);
7560
+ }
7561
+ this.acquiredBaseTextureId = webgl.acquireTexture(id) ? id : null;
7562
+ }
7563
+
7530
7564
  // A texture map is a texture coords point that lines up with the texture
7531
7565
  // vertex point. So, if the vertex shape is rectangular, centered at the
7532
7566
  // origin and wants to incorporate the entire texture, then the map would
@@ -7707,14 +7741,15 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7707
7741
  maskTextures = this.maskTextures,
7708
7742
  webgl = this.webgl,
7709
7743
  gl = this.gl;
7710
- if (texture) {
7711
- if (deleteTexture && webgl.textures[texture.id] != null) {
7712
- webgl.deleteTexture(texture.id);
7713
- }
7714
- if (texture.buffer != null) {
7715
- gl.deleteBuffer(texture.buffer);
7716
- texture.buffer = null;
7717
- }
7744
+ if (deleteTexture && this.acquiredBaseTextureId != null) {
7745
+ // Release exactly the base reference this object acquired, so a failed
7746
+ // acquire (e.g. an atlas not registered yet) can never over-release.
7747
+ webgl.deleteTexture(this.acquiredBaseTextureId);
7748
+ this.acquiredBaseTextureId = null;
7749
+ }
7750
+ if (texture && texture.buffer != null) {
7751
+ gl.deleteBuffer(texture.buffer);
7752
+ texture.buffer = null;
7718
7753
  }
7719
7754
  if (deleteTexture) {
7720
7755
  maskTextures.forEach(function (maskTexture) {
@@ -7994,6 +8029,9 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
7994
8029
  gl.uniform1f(locations.u_z, this.z);
7995
8030
  gl.uniform4f(locations.u_color, color[0], color[1], color[2], color[3]);
7996
8031
  var texture = this.texture;
8032
+ // Set when a textured object's base texture can't be bound, so we skip the
8033
+ // draw rather than sampling a stale/wrong texture (see below).
8034
+ var skipDraw = false;
7997
8035
  if (texture != null && targetTexture === false) {
7998
8036
  // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
7999
8037
  var texSize = 2; // 2 components per iteration
@@ -8007,27 +8045,49 @@ var GLObject = /*#__PURE__*/function (_DrawingObject) {
8007
8045
  gl.enableVertexAttribArray(locations.a_texcoord);
8008
8046
  gl.bindBuffer(gl.ARRAY_BUFFER, texture.buffer);
8009
8047
  gl.vertexAttribPointer(locations.a_texcoord, texSize, texType, texNormalize, texStride, texOffset);
8010
- gl.uniform1i(locations.u_use_texture, 1);
8011
- var index = webglInstance.textures[texture.id].index;
8012
- gl.uniform1i(locations.u_texture, index);
8013
-
8014
- // Bind the mask textures (textureMap color mode), each to its own texture
8015
- // unit and precomputed u_mask{i} sampler. They reuse the a_texcoord /
8016
- // v_texcoord bound above, so no extra attribute is needed. Uses an indexed
8017
- // loop with precomputed uniform names to avoid per-frame allocation.
8018
- var maskTextures = this.maskTextures;
8019
- for (var i = 0; i < maskTextures.length; i += 1) {
8020
- var maskTexture = maskTextures[i];
8021
- var maskLocation = locations[maskTexture.uniformName];
8022
- var maskRegistered = webglInstance.textures[maskTexture.id];
8023
- if (maskLocation != null && maskRegistered != null) {
8024
- gl.uniform1i(maskLocation, maskRegistered.index);
8048
+ // Assign content texture units for this draw from the shared pool. Unit 0
8049
+ // is reserved for the target/selector framebuffer texture, so content
8050
+ // starts at unit 1: the base texture, then each mask texture in turn.
8051
+ // bindTextureToUnit only issues a bindTexture when the unit isn't already
8052
+ // pointing at that texture, so runs of draws sharing a texture (e.g. text
8053
+ // sharing a font atlas) issue no bind calls.
8054
+ var textureUnit = 1;
8055
+ if (webglInstance.bindTextureToUnit(texture.id, textureUnit)) {
8056
+ gl.uniform1i(locations.u_use_texture, 1);
8057
+ gl.uniform1i(locations.u_texture, textureUnit);
8058
+ textureUnit += 1;
8059
+
8060
+ // Bind the mask textures (textureMap color mode), each to its own
8061
+ // texture unit and precomputed u_mask{i} sampler. They reuse the
8062
+ // a_texcoord / v_texcoord bound above, so no extra attribute is needed.
8063
+ // Only assign the sampler if the bind succeeds — otherwise the uniform
8064
+ // would default to sampler 0 (the reserved target texture) and recolor
8065
+ // with garbage. Uses an indexed loop with precomputed uniform names to
8066
+ // avoid per-frame allocation.
8067
+ var maskTextures = this.maskTextures;
8068
+ for (var i = 0; i < maskTextures.length; i += 1) {
8069
+ var maskTexture = maskTextures[i];
8070
+ var maskLocation = locations[maskTexture.uniformName];
8071
+ if (maskLocation != null && webglInstance.bindTextureToUnit(maskTexture.id, textureUnit)) {
8072
+ gl.uniform1i(maskLocation, textureUnit);
8073
+ textureUnit += 1;
8074
+ }
8025
8075
  }
8076
+ } else {
8077
+ // The base texture isn't available (e.g. a shared texture was deleted by
8078
+ // another element's cleanup while this one still references it). The
8079
+ // composed texture shaders sample u_texture unconditionally, so there is
8080
+ // no safe in-shader fallback — skip this object's draw this frame rather
8081
+ // than sampling whatever stale texture occupies the unit.
8082
+ gl.uniform1i(locations.u_use_texture, 0);
8083
+ skipDraw = true;
8026
8084
  }
8027
8085
  } else {
8028
8086
  gl.uniform1i(locations.u_use_texture, 0);
8029
8087
  }
8030
- gl.drawArrays(this.glPrimitive, 0, numDrawVertices);
8088
+ if (!skipDraw) {
8089
+ gl.drawArrays(this.glPrimitive, 0, numDrawVertices);
8090
+ }
8031
8091
  if (texture) {
8032
8092
  gl.disableVertexAttribArray(locations.a_texcoord);
8033
8093
  }
@@ -52888,11 +52948,20 @@ var FigureElementPrimitiveGLText = /*#__PURE__*/function (_FigureElementPrimiti)
52888
52948
  scene: scene,
52889
52949
  font: this.font
52890
52950
  });
52951
+ var textureID = this.atlas.font.getTextureID();
52891
52952
  if (this.drawingObject.texture == null) {
52892
- this.drawingObject.addTexture(this.atlas.font.getTextureID());
52953
+ this.drawingObject.addTexture(textureID);
52893
52954
  } else {
52894
- this.drawingObject.texture.id = this.atlas.font.getTextureID();
52895
- }
52955
+ this.drawingObject.texture.id = textureID;
52956
+ }
52957
+ // Take a webgl reference to the shared atlas texture so it survives other
52958
+ // elements' cleanup. The Atlas registers/uploads the texture; this element
52959
+ // only adopts its id (GLObject.addTexture above doesn't touch webgl), so
52960
+ // without this its resetTextureBuffer release would be unbalanced and the
52961
+ // first element's cleanup would free the atlas for the others.
52962
+ // setBaseTextureRef releases any previously-held id (createAtlas re-runs on
52963
+ // font changes) and is idempotent when the id is unchanged.
52964
+ this.drawingObject.setBaseTextureRef(textureID);
52896
52965
  // console.log(this.atlas)
52897
52966
  this.setText(this.text);
52898
52967
  this.atlasNotificationsID = this.atlas.notifications.add('updated', this.loaded.bind(this));
@@ -67165,6 +67234,20 @@ var WebGLInstance = /*#__PURE__*/function () {
67165
67234
  value:
67166
67235
  // locations: Object;
67167
67236
 
67237
+ // Content texture units are a small shared pool reused across draws. Unit 0 is
67238
+ // reserved for the target/selector framebuffer texture, so content starts at
67239
+ // unit 1. boundUnits[u] tracks which texture id is currently bound to GL unit
67240
+ // u, so bindTextureToUnit can skip redundant binds (bind-on-change).
67241
+
67242
+ // Monotonic source for texture handles (never reused, so deleting a texture
67243
+ // can never cause a later texture to collide with a live one).
67244
+
67245
+ // gl.MAX_TEXTURE_IMAGE_UNITS (the fragment-shader sampler limit), queried once
67246
+ // for a diagnostic warning. Matches the per-object mask guard in
67247
+ // FigurePrimitives.gl().
67248
+
67249
+ // Set once the unit-budget warning has fired, so it isn't logged every frame.
67250
+
67168
67251
  /*
67169
67252
  Add, or update a texture. If the texture already exists, then do nothing.
67170
67253
  A texture is referenced with a unique id, and defined by either a url (string), Image or html canvas element.
@@ -67180,45 +67263,52 @@ var WebGLInstance = /*#__PURE__*/function () {
67180
67263
  var onLoad = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
67181
67264
  var force = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
67182
67265
  /*
67183
- If the texture already exits, then return its index. If the texture is
67184
- still loading, then add the onLoad callback to the list of callbacks to
67185
- be called once the texture loads.
67266
+ A texture id can be shared by multiple owners (e.g. several GLText elements
67267
+ using the same font atlas, plus the Atlas itself). Each addTexture call
67268
+ that isn't a forced content update acquires one reference; deleteTexture
67269
+ releases one, and the GL texture is freed only when the last owner releases
67270
+ it. This lets one element's cleanup() drop its reference without pulling a
67271
+ still-shared texture out from under the survivors.
67272
+ If the texture already exists and is still loading, the onLoad callback is
67273
+ added to the list to be called once the texture loads.
67186
67274
  */
67187
67275
  if (!force && this.textures[id] != null) {
67188
- if (this.textures[id].state === 'loaded') {
67189
- if (onLoad != null) {
67190
- this.textures[id].onLoad.push(onLoad);
67191
- }
67276
+ // Another owner (or the same owner re-acquiring) references an existing
67277
+ // texture: take a reference and (re)register the load callback.
67278
+ var existingTexture = this.textures[id];
67279
+ existingTexture.refCount += 1;
67280
+ if (onLoad != null) {
67281
+ existingTexture.onLoad.push(onLoad);
67282
+ }
67283
+ if (existingTexture.state === 'loaded') {
67192
67284
  this.onLoad(id);
67193
- return this.textures[id].index;
67194
67285
  }
67195
- // Otherwise loading
67286
+ return existingTexture.handle;
67287
+ }
67288
+ var gl = this.gl;
67289
+ if (this.textures[id] != null) {
67290
+ // Forced content update of an existing texture: keep its identity AND
67291
+ // reference count so other owners survive the update. setTextureData
67292
+ // (below) frees and replaces the old glTexture, so the entry — including
67293
+ // its glTexture pointer — is preserved here rather than recreated.
67294
+ // Append (don't replace) onLoad so pending callbacks other owners
67295
+ // registered while the texture was still loading aren't silently dropped.
67296
+ this.textures[id].state = 'loading';
67196
67297
  if (onLoad != null) {
67197
67298
  this.textures[id].onLoad.push(onLoad);
67198
67299
  }
67199
- return this.textures[id].index;
67200
- // removed by dead control flow
67201
-
67202
- }
67203
- var index = 0;
67204
- if (this.textures[id] != null) {
67205
- index = this.textures[id].index;
67206
67300
  } else {
67207
- index = Object.keys(this.textures).length + 1;
67301
+ // Brand new texture: the first owner holds the only reference.
67302
+ this.textures[id] = {
67303
+ id: id,
67304
+ state: 'loading',
67305
+ onLoad: onLoad != null ? [onLoad] : [],
67306
+ handle: this.nextTextureHandle,
67307
+ refCount: 1
67308
+ };
67309
+ this.nextTextureHandle += 1;
67208
67310
  }
67209
- // If a texture already exists, then unload it
67210
- this.deleteTexture(id);
67211
- var gl = this.gl;
67212
- this.textures[id] = {
67213
- id: id,
67214
- state: 'loading',
67215
- onLoad: [],
67216
- index: index
67217
- };
67218
67311
  var texture = this.textures[id];
67219
- if (onLoad != null) {
67220
- texture.onLoad.push(onLoad);
67221
- }
67222
67312
  // If the data is a url string, then load the data into an image
67223
67313
  if (typeof data === 'string') {
67224
67314
  this.setTextureData(id, loadColor);
@@ -67237,7 +67327,7 @@ var WebGLInstance = /*#__PURE__*/function () {
67237
67327
  this.onLoad(id);
67238
67328
  texture.state = 'loaded';
67239
67329
  }
67240
- return this.textures[id].index;
67330
+ return this.textures[id].handle;
67241
67331
  }
67242
67332
  }, {
67243
67333
  key: "getAtlas",
@@ -67273,6 +67363,27 @@ var WebGLInstance = /*#__PURE__*/function () {
67273
67363
  throw errors[0];
67274
67364
  }
67275
67365
  }
67366
+
67367
+ // Take an additional reference to an already-registered texture, without
67368
+ // re-uploading it or touching its load callbacks. Used when an element adopts
67369
+ // a texture another owner created and uploaded (e.g. a GLText element sharing
67370
+ // a font atlas registered by the Atlas). Returns false if the texture isn't
67371
+ // registered yet, in which case no reference was taken. Release with
67372
+ // deleteTexture.
67373
+ }, {
67374
+ key: "acquireTexture",
67375
+ value: function acquireTexture(id) {
67376
+ var texture = this.textures[id];
67377
+ if (texture == null) {
67378
+ return false;
67379
+ }
67380
+ texture.refCount += 1;
67381
+ return true;
67382
+ }
67383
+
67384
+ // Release one reference to a texture. The GL texture is freed only once the
67385
+ // last owner releases it, so one element's cleanup can't delete a texture
67386
+ // another element still shares (see addTexture for the rationale).
67276
67387
  }, {
67277
67388
  key: "deleteTexture",
67278
67389
  value: function deleteTexture(id) {
@@ -67280,13 +67391,27 @@ var WebGLInstance = /*#__PURE__*/function () {
67280
67391
  if (texture == null) {
67281
67392
  return;
67282
67393
  }
67283
- var gl = this.gl;
67394
+ texture.refCount -= 1;
67395
+ if (texture.refCount <= 0) {
67396
+ this.freeTexture(id);
67397
+ }
67398
+ }
67284
67399
 
67285
- // If texture exists, then delete it
67400
+ // Unconditionally free a texture regardless of reference count. Used for
67401
+ // teardown (cleanup), where every owner is going away at once.
67402
+ }, {
67403
+ key: "freeTexture",
67404
+ value: function freeTexture(id) {
67405
+ var texture = this.textures[id];
67406
+ if (texture == null) {
67407
+ return;
67408
+ }
67409
+ var gl = this.gl;
67410
+ // gl.deleteTexture unbinds it from any unit it was bound to, so we just drop
67411
+ // the stale cache entries.
67286
67412
  if (texture.glTexture != null) {
67287
- gl.activeTexture(gl.TEXTURE0 + texture.index);
67288
- gl.bindTexture(gl.TEXTURE_2D, null);
67289
67413
  gl.deleteTexture(texture.glTexture);
67414
+ this.clearBoundUnits(id);
67290
67415
  }
67291
67416
  this.cancel(id);
67292
67417
  delete this.textures[id];
@@ -67298,6 +67423,53 @@ var WebGLInstance = /*#__PURE__*/function () {
67298
67423
  Object.keys(this.textures).forEach(function (id) {
67299
67424
  _this3.textures[id].glTexture = null;
67300
67425
  });
67426
+ // The new context starts with nothing bound, so the bind cache is stale.
67427
+ this.boundUnits = [];
67428
+ }
67429
+
67430
+ // Drop any working-unit cache entries that point at this texture id, so a
67431
+ // future draw re-binds rather than trusting a stale/deleted glTexture.
67432
+ }, {
67433
+ key: "clearBoundUnits",
67434
+ value: function clearBoundUnits(id) {
67435
+ for (var u = 0; u < this.boundUnits.length; u += 1) {
67436
+ if (this.boundUnits[u] === id) {
67437
+ this.boundUnits[u] = null;
67438
+ }
67439
+ }
67440
+ }
67441
+
67442
+ /*
67443
+ Bind a registered texture to a content texture unit for the current draw.
67444
+ Content units are a small shared pool (unit 0 is reserved for the
67445
+ target/selector framebuffer texture). bindTexture is only issued when the
67446
+ unit is not already pointing at this texture, so runs of draws that share a
67447
+ texture (e.g. text sharing a font atlas) issue zero bind calls.
67448
+ */
67449
+ }, {
67450
+ key: "bindTextureToUnit",
67451
+ value: function bindTextureToUnit(id, unit) {
67452
+ var texture = this.textures[id];
67453
+ if (texture == null || texture.glTexture == null) {
67454
+ return false;
67455
+ }
67456
+ if (unit >= this.maxTextureUnits) {
67457
+ // Out of unit budget: warn once (not every frame) and don't issue an
67458
+ // out-of-range bind. The caller treats false as "not bound".
67459
+ if (!this.warnedUnitOverflow) {
67460
+ (0,_tools_tools__WEBPACK_IMPORTED_MODULE_2__.Console)("FigureOne WebGL warning: texture unit ".concat(unit, " exceeds this device's ") + "MAX_TEXTURE_IMAGE_UNITS (".concat(this.maxTextureUnits, "). Reduce the ") + 'number of simultaneous textures/masks.');
67461
+ this.warnedUnitOverflow = true;
67462
+ }
67463
+ return false;
67464
+ }
67465
+ if (this.boundUnits[unit] === id) {
67466
+ return true;
67467
+ }
67468
+ var gl = this.gl;
67469
+ gl.activeTexture(gl.TEXTURE0 + unit);
67470
+ gl.bindTexture(gl.TEXTURE_2D, texture.glTexture);
67471
+ this.boundUnits[unit] = id;
67472
+ return true;
67301
67473
  }
67302
67474
  }, {
67303
67475
  key: "cleanup",
@@ -67311,9 +67483,10 @@ var WebGLInstance = /*#__PURE__*/function () {
67311
67483
  }
67312
67484
  });
67313
67485
  this.programs = [];
67314
- // Delete all textures
67486
+ // Free all textures outright, ignoring reference counts — every owner is
67487
+ // going away in this teardown.
67315
67488
  Object.keys(this.textures).forEach(function (id) {
67316
- _this4.deleteTexture(id);
67489
+ _this4.freeTexture(id);
67317
67490
  });
67318
67491
  this.textures = {};
67319
67492
  // Clean up atlases
@@ -67334,20 +67507,27 @@ var WebGLInstance = /*#__PURE__*/function () {
67334
67507
  return (value & value - 1) === 0;
67335
67508
  }
67336
67509
  var texture = this.textures[id];
67337
- var index = texture.index;
67338
67510
  var gl = this.gl;
67511
+ // Upload happens on the first content unit as scratch. Any cache entry for
67512
+ // this id refers to the old glTexture we're about to replace, so invalidate
67513
+ // them all before binding the new one.
67514
+ var uploadUnit = 1;
67515
+ this.clearBoundUnits(id);
67339
67516
 
67340
67517
  // If texture exists, then delete it
67341
67518
  if (texture.glTexture != null) {
67342
- gl.activeTexture(gl.TEXTURE0 + index);
67519
+ gl.activeTexture(gl.TEXTURE0 + uploadUnit);
67343
67520
  gl.bindTexture(gl.TEXTURE_2D, null);
67344
67521
  gl.deleteTexture(texture.glTexture);
67345
67522
  }
67346
67523
  // Create a texture
67347
67524
  var glTexture = gl.createTexture();
67348
67525
  texture.glTexture = glTexture;
67349
- gl.activeTexture(gl.TEXTURE0 + index);
67526
+ gl.activeTexture(gl.TEXTURE0 + uploadUnit);
67350
67527
  gl.bindTexture(gl.TEXTURE_2D, glTexture);
67528
+ // The new glTexture is now bound to the upload unit; record it so a draw
67529
+ // that needs it on this unit can skip a redundant bind.
67530
+ this.boundUnits[uploadUnit] = id;
67351
67531
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
67352
67532
 
67353
67533
  // If image is a color, then create s ingle pixel image of that color
@@ -67411,7 +67591,7 @@ var WebGLInstance = /*#__PURE__*/function () {
67411
67591
  value: function onLoad(id) {
67412
67592
  var _this5 = this;
67413
67593
  this.textures[id].onLoad.forEach(function (f) {
67414
- return _this5.fnMap.exec(f, true, _this5.textures[id].index);
67594
+ return _this5.fnMap.exec(f, true, _this5.textures[id].handle);
67415
67595
  });
67416
67596
  this.textures[id].onLoad = [];
67417
67597
  }
@@ -67420,7 +67600,7 @@ var WebGLInstance = /*#__PURE__*/function () {
67420
67600
  value: function cancel(id) {
67421
67601
  var _this6 = this;
67422
67602
  this.textures[id].onLoad.forEach(function (f) {
67423
- return _this6.fnMap.exec(f, false, _this6.textures[id].index);
67603
+ return _this6.fnMap.exec(f, false, _this6.textures[id].handle);
67424
67604
  });
67425
67605
  this.textures[id].onLoad = [];
67426
67606
  }
@@ -67485,6 +67665,11 @@ var WebGLInstance = /*#__PURE__*/function () {
67485
67665
  value: function init(gl) {
67486
67666
  this.gl = gl;
67487
67667
  this.textures = {};
67668
+ this.boundUnits = [];
67669
+ this.nextTextureHandle = 1;
67670
+ this.warnedUnitOverflow = false;
67671
+ var maxUnits = gl.getParameter ? gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) : 0;
67672
+ this.maxTextureUnits = maxUnits || 8;
67488
67673
  this.programs = [];
67489
67674
  this.targetTexture = null;
67490
67675
  this.lastUsedProgram = null;
@@ -82098,8 +82283,8 @@ var tools = {
82098
82283
  */
82099
82284
 
82100
82285
  var Fig = {
82101
- version: "1.8.0",
82102
- gitHash: "4b64a8de5",
82286
+ version: "1.9.0",
82287
+ gitHash: "2e042f98b",
82103
82288
  tools: tools,
82104
82289
  Figure: _js_figure_Figure__WEBPACK_IMPORTED_MODULE_5__["default"],
82105
82290
  Recorder: _js_figure_Recorder_Recorder__WEBPACK_IMPORTED_MODULE_7__.Recorder,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figureone",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Draw, animate and interact with shapes, text, plots and equations in Javascript. Create interactive slide shows, and interactive videos.",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -76,6 +76,7 @@ declare class GLObject extends DrawingObject {
76
76
  fragmentShader: TypeFragmentShader;
77
77
  selectorVertexShader: TypeVertexShader;
78
78
  selectorFragmentShader: TypeFragmentShader;
79
+ acquiredBaseTextureId: string | null;
79
80
  constructor(webgl: WebGLInstance, vertexShader?: TypeVertexShader, fragmentShader?: TypeFragmentShader, selectorVertexShader?: TypeVertexShader, selectorFragShader?: TypeFragmentShader);
80
81
  init(webgl: WebGLInstance): void;
81
82
  initProgram(): void;
@@ -105,6 +106,18 @@ declare class GLObject extends DrawingObject {
105
106
  addMaskTexture(location?: string, loadColor?: TypeColor): void;
106
107
  updateTexture(data: HTMLImageElement): void;
107
108
  initTexture(force?: boolean): void;
109
+ /**
110
+ * Adopt a base-texture reference to an already-registered texture (e.g. a
111
+ * shared font atlas uploaded by the Atlas, whose id this object renders with
112
+ * but does not upload itself).
113
+ *
114
+ * Releases any previously-held base reference first (so a font/atlas change
115
+ * rebalances correctly) and is idempotent when the id is unchanged. If the
116
+ * texture isn't registered yet, no reference is taken and acquiredBaseTextureId
117
+ * is cleared, so the later resetTextureBuffer release stays balanced (it only
118
+ * releases a reference that was actually acquired).
119
+ */
120
+ setBaseTextureRef(id: string): void;
108
121
  createTextureMap(xMinGL?: number, xMaxGL?: number, yMinGL?: number, yMaxGL?: number, xMinTex?: number, xMaxTex?: number, yMinTex?: number, yMaxTex?: number): void;
109
122
  addVertices(vertices: Array<number>, dimension?: 2 | 3, usage?: TypeGLBufferUsage): void;
110
123
  addVertices3(vertices: Array<number>, usage?: TypeGLBufferUsage): void;
@@ -12,11 +12,16 @@ declare class WebGLInstance {
12
12
  textures: {
13
13
  [name: string]: {
14
14
  glTexture: WebGLTexture;
15
- index: number;
15
+ handle: number;
16
+ refCount: number;
16
17
  state: 'loading' | 'loaded';
17
18
  onLoad: Array<((b: boolean, n: number) => void) | string>;
18
19
  };
19
20
  };
21
+ boundUnits: Array<string | null>;
22
+ nextTextureHandle: number;
23
+ maxTextureUnits: number;
24
+ warnedUnitOverflow: boolean;
20
25
  atlases: {
21
26
  [atlasId: string]: Atlas;
22
27
  };
@@ -39,8 +44,12 @@ declare class WebGLInstance {
39
44
  addTexture(id: string, data: string | HTMLImageElement | HTMLCanvasElement, loadColor?: TypeColor, repeat?: boolean, onLoad?: null | string | ((b: boolean, n: number) => void), force?: boolean): number;
40
45
  getAtlas(options: OBJ_Atlas): Atlas;
41
46
  recreateAtlases(): void;
47
+ acquireTexture(id: string): boolean;
42
48
  deleteTexture(id: string): void;
49
+ freeTexture(id: string): void;
43
50
  contextLost(): void;
51
+ clearBoundUnits(id: string): void;
52
+ bindTextureToUnit(id: string, unit: number): boolean;
44
53
  cleanup(): void;
45
54
  setTextureData(id: string, image: Record<string, any> | TypeColor, // image data
46
55
  repeat?: boolean): boolean;