modern-canvas 0.8.1 → 0.8.3

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/index.mjs CHANGED
@@ -870,14 +870,14 @@ class Input extends EventEmitter {
870
870
  let IID = 0;
871
871
  class CoreObject extends EventEmitter {
872
872
  instanceId = ++IID;
873
- _customPropertyAccessor;
873
+ _propertyAccessor;
874
874
  _properties = /* @__PURE__ */ new Map();
875
875
  _updatedProperties = /* @__PURE__ */ new Map();
876
876
  _changedProperties = /* @__PURE__ */ new Set();
877
877
  _updatingPromise = Promise.resolve();
878
878
  _updating = false;
879
879
  useCustomPropertyAccessor(accessor) {
880
- this._customPropertyAccessor = accessor;
880
+ this._propertyAccessor = accessor;
881
881
  this.getPropertyDeclarations().forEach((declaration, key) => {
882
882
  const newValue = accessor.get(key, () => void 0);
883
883
  const oldValue = this._properties.get(key);
@@ -901,15 +901,15 @@ class CoreObject extends EventEmitter {
901
901
  if (context?.declaration.protected) {
902
902
  return this[context.internalKey];
903
903
  } else {
904
- return this._customPropertyAccessor ? this._customPropertyAccessor.get(key, () => this._properties.get(key)) : this._properties.get(key);
904
+ return this._propertyAccessor ? this._propertyAccessor.get(key, () => this._properties.get(key)) : this._properties.get(key);
905
905
  }
906
906
  }
907
907
  setter(key, value, context) {
908
908
  if (context?.declaration.protected) {
909
909
  this[context.internalKey] = value;
910
910
  } else {
911
- if (this._customPropertyAccessor) {
912
- this._customPropertyAccessor.set(key, value);
911
+ if (this._propertyAccessor) {
912
+ this._propertyAccessor.set(key, value);
913
913
  }
914
914
  this._properties.set(key, value);
915
915
  }
@@ -1118,6 +1118,9 @@ class Color {
1118
1118
  }
1119
1119
  return (alpha * 255 << 24) + (r << 16) + (g << 8) + b;
1120
1120
  }
1121
+ toInt8Array() {
1122
+ return [this.r8, this.g8, this.b8, this.a8];
1123
+ }
1121
1124
  toArray() {
1122
1125
  return [this.r, this.g, this.b, this.a];
1123
1126
  }
@@ -2531,8 +2534,8 @@ class WebGLBatch2DModule extends WebGLModule {
2531
2534
  _state = WebGLState.for2D();
2532
2535
  _batchSize = 4096 * 4;
2533
2536
  _drawCallUid = 0;
2534
- _defaultModulate = 4294967295;
2535
- _defaultBackgroundColor = 0;
2537
+ _defaultModulate = [255, 255, 255, 255];
2538
+ _defaultBackgroundColor = [0, 0, 0, 0];
2536
2539
  _batchables = [];
2537
2540
  _vertexCount = 0;
2538
2541
  _indexCount = 0;
@@ -2550,7 +2553,7 @@ class WebGLBatch2DModule extends WebGLModule {
2550
2553
  // 1
2551
2554
  aBackgroundColor: { size: 4, normalized: true, type: "unsigned_byte" },
2552
2555
  // 1
2553
- aDisableWrapMode: { size: 4, normalized: true, type: "unsigned_byte" }
2556
+ aDisableWrapMode: { size: 1, normalized: true, type: "float" }
2554
2557
  // 1
2555
2558
  };
2556
2559
  _vertexSize = 1 + 2 + 2 + 1 + 1 + 1;
@@ -2570,7 +2573,7 @@ attribute vec2 aPosition;
2570
2573
  attribute vec2 aUv;
2571
2574
  attribute vec4 aModulate;
2572
2575
  attribute vec4 aBackgroundColor;
2573
- attribute vec4 aDisableWrapMode;
2576
+ attribute float aDisableWrapMode;
2574
2577
 
2575
2578
  uniform mat3 projectionMatrix;
2576
2579
  uniform mat3 viewMatrix;
@@ -2582,7 +2585,7 @@ varying float vTextureId;
2582
2585
  varying vec2 vUv;
2583
2586
  varying vec4 vModulate;
2584
2587
  varying vec4 vBackgroundColor;
2585
- varying vec4 vDisableWrapMode;
2588
+ varying float vDisableWrapMode;
2586
2589
 
2587
2590
  vec2 roundPixels(vec2 position, vec2 targetSize) {
2588
2591
  return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
@@ -2597,6 +2600,7 @@ void main(void) {
2597
2600
  vTextureId = aTextureId;
2598
2601
  vec3 pos = projectionMatrix * viewMatrix * modelMatrix * vec3(aPosition, 1.0);
2599
2602
  gl_Position = vec4(roundPixels(pos.xy, vec2(canvasWidth, canvasHeight)), 0.0, 1.0);
2603
+ // gl_Position = vec4(pos.xy, 0.0, 1.0);
2600
2604
 
2601
2605
  vUv = aUv;
2602
2606
  vModulate = aModulate * modulate;
@@ -2608,20 +2612,20 @@ varying float vTextureId;
2608
2612
  varying vec2 vUv;
2609
2613
  varying vec4 vModulate;
2610
2614
  varying vec4 vBackgroundColor;
2611
- varying vec4 vDisableWrapMode;
2615
+ varying float vDisableWrapMode;
2612
2616
 
2613
2617
  uniform sampler2D samplers[${maxTextureUnits}];
2614
2618
 
2615
2619
  void main(void) {
2616
- vec4 color;
2617
- if (vDisableWrapMode.x > 0.0 && (vUv.x < 0.0 || vUv.y < 0.0 || vUv.x > 1.0 || vUv.y > 1.0))
2620
+ vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
2621
+ if (vDisableWrapMode > 0.0 && (vUv.x < 0.0 || vUv.y < 0.0 || vUv.x > 1.0 || vUv.y > 1.0))
2618
2622
  {
2619
- color = vec4(0.0, 0.0, 0.0, 0.0);
2623
+ //
2620
2624
  }
2621
2625
  else
2622
2626
  if (vTextureId < 0.0)
2623
2627
  {
2624
- color = vec4(0.0, 0.0, 0.0, 0.0);
2628
+ //
2625
2629
  }${Array.from({ length: maxTextureUnits }, (_, i) => {
2626
2630
  let text = " ";
2627
2631
  if (i >= 0) {
@@ -2715,7 +2719,7 @@ void main(void) {
2715
2719
  const textureMaxUnits = this._renderer.texture.maxUnits;
2716
2720
  const attributeBuffer = this._getAttributeBuffer(vertexCount);
2717
2721
  const float32View = new Float32Array(attributeBuffer);
2718
- const uint32View = new Uint32Array(attributeBuffer);
2722
+ const uint8View = new Uint8Array(attributeBuffer);
2719
2723
  const indexBuffer = this._getIndexBuffer(indexCount);
2720
2724
  let aIndex = 0;
2721
2725
  let iIndex = 0;
@@ -2756,7 +2760,7 @@ void main(void) {
2756
2760
  drawCall.first = iIndex;
2757
2761
  }
2758
2762
  const iIndexStart = aIndex / this._vertexSize;
2759
- const textureLocation = (texture2 ? textureLocationMap.get(texture2) : 255) ?? 255;
2763
+ const textureLocation = (texture2 ? textureLocationMap.get(texture2) : -1) ?? -1;
2760
2764
  const disableWrapModeInt = disableWrapMode ? 1 : 0;
2761
2765
  for (let len2 = vertices.length, i2 = 0; i2 < len2; i2 += 2) {
2762
2766
  float32View[aIndex++] = textureLocation;
@@ -2764,9 +2768,23 @@ void main(void) {
2764
2768
  float32View[aIndex++] = vertices[i2 + 1];
2765
2769
  float32View[aIndex++] = uvs[i2];
2766
2770
  float32View[aIndex++] = uvs[i2 + 1];
2767
- uint32View[aIndex++] = modulate;
2768
- uint32View[aIndex++] = backgroundColor;
2769
- uint32View[aIndex++] = disableWrapModeInt;
2771
+ if (modulate) {
2772
+ const aU8Index = aIndex * 4;
2773
+ uint8View[aU8Index] = modulate[0];
2774
+ uint8View[aU8Index + 1] = modulate[1];
2775
+ uint8View[aU8Index + 2] = modulate[2];
2776
+ uint8View[aU8Index + 3] = modulate[3];
2777
+ }
2778
+ aIndex++;
2779
+ if (backgroundColor) {
2780
+ const aU8Index = aIndex * 4;
2781
+ uint8View[aU8Index] = backgroundColor[0];
2782
+ uint8View[aU8Index + 1] = backgroundColor[1];
2783
+ uint8View[aU8Index + 2] = backgroundColor[2];
2784
+ uint8View[aU8Index + 3] = backgroundColor[3];
2785
+ }
2786
+ aIndex++;
2787
+ float32View[aIndex++] = disableWrapModeInt;
2770
2788
  }
2771
2789
  for (let len2 = indices.length, i2 = 0; i2 < len2; i2++) {
2772
2790
  indexBuffer[iIndex++] = iIndexStart + indices[i2];
@@ -5551,14 +5569,20 @@ class CanvasContext extends Path2D {
5551
5569
  // custom
5552
5570
  uvTransform;
5553
5571
  vertTransform;
5554
- _defaultStyle = Texture2D.EMPTY;
5555
5572
  _draws = [];
5556
- _toTexture(source) {
5557
- if (source instanceof Texture2D) {
5558
- return source;
5559
- } else {
5560
- return ColorTexture.get(source);
5573
+ _parseDrawStyle(source) {
5574
+ if (source) {
5575
+ if (source instanceof Texture2D) {
5576
+ return {
5577
+ texture: source
5578
+ };
5579
+ } else {
5580
+ return {
5581
+ backgroundColor: new Color(source).toInt8Array()
5582
+ };
5583
+ }
5561
5584
  }
5585
+ return {};
5562
5586
  }
5563
5587
  stroke(options) {
5564
5588
  if (!this.curves.length) {
@@ -5579,12 +5603,12 @@ class CanvasContext extends Path2D {
5579
5603
  }
5580
5604
  this._draws.push({
5581
5605
  ...options,
5606
+ ...this._parseDrawStyle(strokeStyle),
5582
5607
  type: "stroke",
5583
5608
  path: new Path2D(this),
5584
- texture: strokeStyle ? this._toTexture(strokeStyle) : this._defaultStyle,
5585
5609
  uvTransform: this.uvTransform,
5586
5610
  vertTransform: this.vertTransform,
5587
- style: {
5611
+ lineStyle: {
5588
5612
  alignment: this.strokeAlignment ?? 0.5,
5589
5613
  cap: this.lineCap ?? "butt",
5590
5614
  join: this.lineJoin ?? "miter",
@@ -5619,9 +5643,9 @@ class CanvasContext extends Path2D {
5619
5643
  }
5620
5644
  this._draws.push({
5621
5645
  ...options,
5646
+ ...this._parseDrawStyle(fillStyle),
5622
5647
  type: "fill",
5623
5648
  path: new Path2D(this),
5624
- texture: fillStyle ? this._toTexture(fillStyle) : this._defaultStyle,
5625
5649
  uvTransform: this.uvTransform,
5626
5650
  vertTransform: this.vertTransform
5627
5651
  });
@@ -5697,17 +5721,20 @@ class CanvasContext extends Path2D {
5697
5721
  current.path.strokeTriangulate({
5698
5722
  vertices,
5699
5723
  indices,
5700
- lineStyle: current.style,
5724
+ lineStyle: current.lineStyle,
5701
5725
  flipAlignment: false,
5702
5726
  closed: true
5703
5727
  });
5704
5728
  }
5705
- this.buildUvs(0, vertices, uvs, current.texture, current.uvTransform);
5729
+ if (current.texture) {
5730
+ this.buildUvs(0, vertices, uvs, current.texture, current.uvTransform);
5731
+ }
5706
5732
  batchables.push({
5707
5733
  vertices: new Float32Array(vertices),
5708
5734
  indices: new Float32Array(indices),
5709
5735
  uvs: new Float32Array(uvs),
5710
5736
  texture: current.texture,
5737
+ backgroundColor: current.backgroundColor,
5711
5738
  type: current.type,
5712
5739
  disableWrapMode: current.disableWrapMode,
5713
5740
  vertTransform: current.vertTransform
@@ -6479,7 +6506,7 @@ let CanvasItem = class extends TimelineNode {
6479
6506
  return batchables.map((batchable) => {
6480
6507
  return {
6481
6508
  ...batchable,
6482
- modulate: this._modulate.toArgb(this.globalOpacity, true),
6509
+ modulate: this._modulate.toInt8Array(),
6483
6510
  blendMode: this.blendMode
6484
6511
  };
6485
6512
  });
@@ -7232,7 +7259,7 @@ let Node2D = class extends CanvasItem {
7232
7259
  super._updateProperty(key, value, oldValue, declaration);
7233
7260
  switch (key) {
7234
7261
  case "rotation":
7235
- this.requestRelayout();
7262
+ this.updateGlobalTransform();
7236
7263
  break;
7237
7264
  }
7238
7265
  }
@@ -9324,6 +9351,45 @@ ZoomBlurEffect = __decorateClass$t([
9324
9351
  customNode("ZoomBlurEffect")
9325
9352
  ], ZoomBlurEffect);
9326
9353
 
9354
+ function getDrawOptions(fill, size) {
9355
+ let disableWrapMode = false;
9356
+ const { width, height } = size;
9357
+ const uvTransform = new Transform2D().scale(1 / width, 1 / height);
9358
+ if (fill.cropRect) {
9359
+ const {
9360
+ left = 0,
9361
+ top = 0,
9362
+ right = 0,
9363
+ bottom = 0
9364
+ } = fill.cropRect;
9365
+ uvTransform.scale(
9366
+ Math.abs(1 - (left + right)),
9367
+ Math.abs(1 - (top + bottom))
9368
+ ).translate(left, top);
9369
+ disableWrapMode = true;
9370
+ }
9371
+ if (fill.tile) {
9372
+ const {
9373
+ translateX = 0,
9374
+ translateY = 0,
9375
+ scaleX = 1,
9376
+ scaleY = 1
9377
+ // flip, TODO
9378
+ // alignment, TODO
9379
+ } = fill.tile;
9380
+ uvTransform.translate(-translateX / width, -translateY / height).scale(1 / scaleX, 1 / scaleY);
9381
+ disableWrapMode = true;
9382
+ } else if (fill.stretchRect) {
9383
+ const { left = 0, top = 0, right = 0, bottom = 0 } = fill.stretchRect;
9384
+ uvTransform.scale(
9385
+ Math.abs(1 - (-left + -right)),
9386
+ Math.abs(1 - (-top + -bottom))
9387
+ ).translate(-left, -top);
9388
+ disableWrapMode = true;
9389
+ }
9390
+ return { disableWrapMode, uvTransform };
9391
+ }
9392
+
9327
9393
  var __defProp$l = Object.defineProperty;
9328
9394
  var __decorateClass$s = (decorators, target, key, kind) => {
9329
9395
  var result = void 0 ;
@@ -9390,47 +9456,12 @@ class BaseElement2DFill extends CoreObject {
9390
9456
  this.enabled && (this._texture || this.color)
9391
9457
  );
9392
9458
  }
9393
- _getDrawOptions() {
9394
- let disableWrapMode = false;
9395
- const { width, height } = this.parent.size;
9396
- const uvTransform = new Transform2D().scale(1 / width, 1 / height);
9397
- if (this.cropRect) {
9398
- const {
9399
- left = 0,
9400
- top = 0,
9401
- right = 0,
9402
- bottom = 0
9403
- } = this.cropRect;
9404
- uvTransform.scale(
9405
- Math.abs(1 - (left + right)),
9406
- Math.abs(1 - (top + bottom))
9407
- ).translate(left, top);
9408
- disableWrapMode = true;
9409
- }
9410
- if (this.tile) {
9411
- const {
9412
- translateX = 0,
9413
- translateY = 0,
9414
- scaleX = 1,
9415
- scaleY = 1
9416
- // flip, TODO
9417
- // alignment, TODO
9418
- } = this.tile;
9419
- uvTransform.translate(-translateX / width, -translateY / height).scale(1 / scaleX, 1 / scaleY);
9420
- disableWrapMode = true;
9421
- } else if (this.stretchRect) {
9422
- const { left = 0, top = 0, right = 0, bottom = 0 } = this.stretchRect;
9423
- uvTransform.scale(
9424
- Math.abs(1 - (-left + -right)),
9425
- Math.abs(1 - (-top + -bottom))
9426
- ).translate(-left, -top);
9427
- disableWrapMode = true;
9428
- }
9429
- return { disableWrapMode, uvTransform };
9430
- }
9431
9459
  draw() {
9432
9460
  const ctx = this.parent.context;
9433
- const { uvTransform, disableWrapMode } = this._getDrawOptions();
9461
+ const { uvTransform, disableWrapMode } = getDrawOptions(
9462
+ this,
9463
+ this.parent.size
9464
+ );
9434
9465
  ctx.uvTransform = uvTransform;
9435
9466
  ctx.fillStyle = this._texture ?? this.color;
9436
9467
  ctx.fill({
@@ -9562,7 +9593,10 @@ class BaseElement2DOutline extends BaseElement2DFill {
9562
9593
  }
9563
9594
  draw() {
9564
9595
  const ctx = this.parent.context;
9565
- const { uvTransform, disableWrapMode } = this._getDrawOptions();
9596
+ const { uvTransform, disableWrapMode } = getDrawOptions(
9597
+ this,
9598
+ this.parent.size
9599
+ );
9566
9600
  ctx.lineWidth = this.width || 1;
9567
9601
  ctx.uvTransform = uvTransform;
9568
9602
  ctx.strokeStyle = this._texture ?? this.color;
@@ -9785,6 +9819,7 @@ class BaseElement2DText extends CoreObject {
9785
9819
  }
9786
9820
  base = new Text();
9787
9821
  measureResult;
9822
+ _textures = [];
9788
9823
  setProperties(properties) {
9789
9824
  return super.setProperties(
9790
9825
  isNone(properties) ? void 0 : normalizeText(properties)
@@ -9798,12 +9833,34 @@ class BaseElement2DText extends CoreObject {
9798
9833
  case "effects":
9799
9834
  case "measureDom":
9800
9835
  case "fonts":
9836
+ this.parent.requestRedraw();
9837
+ break;
9801
9838
  case "fill":
9839
+ this._updateTexture(0, value);
9840
+ break;
9802
9841
  case "outline":
9803
- this.parent.requestRedraw();
9842
+ this._updateTexture(1, value);
9804
9843
  break;
9805
9844
  }
9806
9845
  }
9846
+ async _updateTexture(index, fill) {
9847
+ this._textures[index] = await this._loadTexture(fill);
9848
+ this.parent.requestRedraw();
9849
+ }
9850
+ async _loadTexture(fill) {
9851
+ if (fill.linearGradient || fill.radialGradient) {
9852
+ return new GradientTexture(
9853
+ fill.linearGradient ?? fill.radialGradient,
9854
+ this.parent.size.width,
9855
+ this.parent.size.height
9856
+ );
9857
+ } else if (!isNone(fill.image)) {
9858
+ this.parent.tree?.log(`load image ${fill.image}`);
9859
+ return await assets.texture.load(fill.image);
9860
+ } else {
9861
+ return void 0;
9862
+ }
9863
+ }
9807
9864
  setContent(content) {
9808
9865
  this.content = normalizeTextContent(content);
9809
9866
  }
@@ -9831,9 +9888,45 @@ class BaseElement2DText extends CoreObject {
9831
9888
  this.base.update();
9832
9889
  this.base.pathSets.forEach((pathSet) => {
9833
9890
  pathSet.paths.forEach((path) => {
9834
- ctx.addPath(path);
9835
- ctx.style = { ...path.style };
9836
- ctx.fill();
9891
+ if (path.style.stroke && !isNone(path.style.stroke)) {
9892
+ if (typeof path.style.stroke === "object") {
9893
+ const outline = path.style.stroke;
9894
+ if (outline.enabled !== false && (this._textures[0] || outline.color) && (outline.width === void 0 || outline.width)) {
9895
+ const { uvTransform, disableWrapMode } = getDrawOptions(outline, this.parent.size);
9896
+ ctx.addPath(path);
9897
+ ctx.style = { ...path.style };
9898
+ ctx.lineWidth = outline.width || 1;
9899
+ ctx.uvTransform = uvTransform;
9900
+ ctx.strokeStyle = this._textures[0] ?? outline.color;
9901
+ ctx.lineCap = outline.lineCap;
9902
+ ctx.lineJoin = outline.lineJoin;
9903
+ ctx.stroke({ disableWrapMode });
9904
+ }
9905
+ } else {
9906
+ ctx.addPath(path);
9907
+ ctx.style = { ...path.style };
9908
+ ctx.stroke();
9909
+ }
9910
+ }
9911
+ if (path.style.fill && !isNone(path.style.fill)) {
9912
+ if (typeof path.style.fill === "object") {
9913
+ const fill = path.style.fill;
9914
+ if (fill.enabled !== false && (this._textures[1] || fill.color)) {
9915
+ const { uvTransform, disableWrapMode } = getDrawOptions(fill, this.parent.size);
9916
+ ctx.addPath(path);
9917
+ ctx.style = { ...path.style };
9918
+ ctx.uvTransform = uvTransform;
9919
+ ctx.fillStyle = this._textures[1] ?? fill.color;
9920
+ ctx.fill({
9921
+ disableWrapMode
9922
+ });
9923
+ }
9924
+ } else {
9925
+ ctx.addPath(path);
9926
+ ctx.style = { ...path.style };
9927
+ ctx.fill();
9928
+ }
9929
+ }
9837
9930
  });
9838
9931
  });
9839
9932
  }
@@ -14228,7 +14321,11 @@ class Engine extends SceneTree {
14228
14321
  return this.renderer.toPixels();
14229
14322
  }
14230
14323
  toImageData() {
14231
- return new ImageData(this.toPixels(), this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
14324
+ return new ImageData(
14325
+ this.toPixels(),
14326
+ this.gl.drawingBufferWidth,
14327
+ this.gl.drawingBufferHeight
14328
+ );
14232
14329
  }
14233
14330
  toCanvas2D() {
14234
14331
  const imageData = this.toImageData();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modern-canvas",
3
3
  "type": "module",
4
- "version": "0.8.1",
4
+ "version": "0.8.3",
5
5
  "packageManager": "pnpm@9.15.1",
6
6
  "description": "A JavaScript WebGL rendering engine.",
7
7
  "author": "wxm",
@@ -84,7 +84,7 @@
84
84
  "@types/node": "^24.3.0",
85
85
  "bumpp": "^10.2.3",
86
86
  "conventional-changelog-cli": "^5.0.0",
87
- "eslint": "^9.33.0",
87
+ "eslint": "^9.34.0",
88
88
  "lint-staged": "^16.1.5",
89
89
  "lottie-web": "^5.13.0",
90
90
  "modern-gif": "^2.0.4",