modern-canvas 0.8.5 → 0.8.7

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
@@ -1,8 +1,8 @@
1
1
  import { defineProperty, EventEmitter, getDeclarations, parseColor, property, RawWeakMap as RawWeakMap$1, isGradient, isColorFillObject, clearUndef, idGenerator, normalizeFill, isNone, normalizeBackground, normalizeForeground, normalizeOutline, normalizeShadow, normalizeShape, getDefaultStyle, normalizeText, normalizeTextContent } from 'modern-idoc';
2
2
  import { extend } from 'colord';
3
3
  import namesPlugin from 'colord/plugins/names';
4
- import { Path2D, Path2DSet, svgToDom, svgToPath2DSet, Matrix3 as Matrix3$1 } from 'modern-path2d';
5
- import { Text } from 'modern-text';
4
+ import { Path2D, Path2DSet, svgToDom, svgToPath2DSet, Matrix3 as Matrix3$1, BoundingBox } from 'modern-path2d';
5
+ import { Text, Character } from 'modern-text';
6
6
 
7
7
  const customNodes = /* @__PURE__ */ new Map();
8
8
  function customNode(name, defaultProperties) {
@@ -5120,21 +5120,23 @@ class GradientTexture extends Texture2D {
5120
5120
  if (!ctx) {
5121
5121
  throw new Error("Failed to parse linear gradient, get canvas context is null.");
5122
5122
  }
5123
- let { angle = 0, stops } = linearGradient;
5124
- angle -= Math.PI / 2;
5125
- const halfWidth = width / 2;
5126
- const halfHeight = height / 2;
5127
- const length = Math.sqrt(width * width + height * height) / 2;
5128
- const x0 = halfWidth + length * Math.cos(angle + Math.PI);
5129
- const y0 = halfHeight + length * Math.sin(angle + Math.PI);
5130
- const x1 = halfWidth + length * Math.cos(angle);
5131
- const y1 = halfHeight + length * Math.sin(angle);
5132
- const gradient = ctx.createLinearGradient(x0, y0, x1, y1);
5133
- stops.forEach((stop) => {
5134
- gradient.addColorStop(stop.offset, stop.color);
5135
- });
5136
- ctx.fillStyle = gradient;
5137
- ctx.fillRect(0, 0, canvas.width, canvas.height);
5123
+ const { angle = 0, stops } = linearGradient;
5124
+ const w = width;
5125
+ const h = height;
5126
+ const cx = w / 2;
5127
+ const cy = h / 2;
5128
+ const A = (angle + 90) * Math.PI / 180;
5129
+ const dx = Math.sin(A);
5130
+ const dy = -Math.cos(A);
5131
+ const L = Math.abs(w * Math.sin(A)) + Math.abs(h * Math.cos(A));
5132
+ const x0 = cx - dx * (L / 2);
5133
+ const y0 = cy - dy * (L / 2);
5134
+ const x1 = cx + dx * (L / 2);
5135
+ const y1 = cy + dy * (L / 2);
5136
+ const g = ctx.createLinearGradient(x0, y0, x1, y1);
5137
+ for (const s of stops) g.addColorStop(s.offset, s.color);
5138
+ ctx.fillStyle = g;
5139
+ ctx.fillRect(0, 0, w, h);
5138
5140
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
5139
5141
  return {
5140
5142
  width: imageData.width,
@@ -9351,21 +9353,21 @@ ZoomBlurEffect = __decorateClass$t([
9351
9353
  customNode("ZoomBlurEffect")
9352
9354
  ], ZoomBlurEffect);
9353
9355
 
9354
- function getDrawOptions(fill, size) {
9356
+ function getDrawOptions(fill, box) {
9355
9357
  let disableWrapMode = false;
9356
- const { width, height } = size;
9357
- const uvTransform = new Transform2D().scale(1 / width, 1 / height);
9358
+ const { left = 0, top = 0, width, height } = box;
9359
+ const uvTransform = new Transform2D().translate(-left, -top).scale(1 / width, 1 / height);
9358
9360
  if (fill.cropRect) {
9359
9361
  const {
9360
- left = 0,
9361
- top = 0,
9362
+ left: left2 = 0,
9363
+ top: top2 = 0,
9362
9364
  right = 0,
9363
9365
  bottom = 0
9364
9366
  } = fill.cropRect;
9365
9367
  uvTransform.scale(
9366
- Math.abs(1 - (left + right)),
9367
- Math.abs(1 - (top + bottom))
9368
- ).translate(left, top);
9368
+ Math.abs(1 - (left2 + right)),
9369
+ Math.abs(1 - (top2 + bottom))
9370
+ ).translate(left2, top2);
9369
9371
  disableWrapMode = true;
9370
9372
  }
9371
9373
  if (fill.tile) {
@@ -9380,11 +9382,16 @@ function getDrawOptions(fill, size) {
9380
9382
  uvTransform.translate(-translateX / width, -translateY / height).scale(1 / scaleX, 1 / scaleY);
9381
9383
  disableWrapMode = true;
9382
9384
  } else if (fill.stretchRect) {
9383
- const { left = 0, top = 0, right = 0, bottom = 0 } = fill.stretchRect;
9385
+ const {
9386
+ left: left2 = 0,
9387
+ top: top2 = 0,
9388
+ right = 0,
9389
+ bottom = 0
9390
+ } = fill.stretchRect;
9384
9391
  uvTransform.scale(
9385
- Math.abs(1 - (-left + -right)),
9386
- Math.abs(1 - (-top + -bottom))
9387
- ).translate(-left, -top);
9392
+ Math.abs(1 - (-left2 + -right)),
9393
+ Math.abs(1 - (-top2 + -bottom))
9394
+ ).translate(-left2, -top2);
9388
9395
  disableWrapMode = true;
9389
9396
  }
9390
9397
  return { disableWrapMode, uvTransform };
@@ -9460,7 +9467,10 @@ class BaseElement2DFill extends CoreObject {
9460
9467
  const ctx = this.parent.context;
9461
9468
  const { uvTransform, disableWrapMode } = getDrawOptions(
9462
9469
  this,
9463
- this.parent.size
9470
+ {
9471
+ width: this.parent.size.width,
9472
+ height: this.parent.size.height
9473
+ }
9464
9474
  );
9465
9475
  ctx.uvTransform = uvTransform;
9466
9476
  ctx.fillStyle = this._texture ?? this.color;
@@ -9595,7 +9605,10 @@ class BaseElement2DOutline extends BaseElement2DFill {
9595
9605
  const ctx = this.parent.context;
9596
9606
  const { uvTransform, disableWrapMode } = getDrawOptions(
9597
9607
  this,
9598
- this.parent.size
9608
+ {
9609
+ width: this.parent.size.width,
9610
+ height: this.parent.size.height
9611
+ }
9599
9612
  );
9600
9613
  ctx.lineWidth = this.width || 1;
9601
9614
  ctx.uvTransform = uvTransform;
@@ -9819,7 +9832,7 @@ class BaseElement2DText extends CoreObject {
9819
9832
  }
9820
9833
  base = new Text();
9821
9834
  measureResult;
9822
- _textures = [];
9835
+ _textureMap = /* @__PURE__ */ new Map();
9823
9836
  setProperties(properties) {
9824
9837
  return super.setProperties(
9825
9838
  isNone(properties) ? void 0 : normalizeText(properties)
@@ -9829,30 +9842,72 @@ class BaseElement2DText extends CoreObject {
9829
9842
  super._updateProperty(key, value, oldValue, declaration);
9830
9843
  switch (key) {
9831
9844
  case "enabled":
9832
- case "content":
9833
9845
  case "effects":
9834
9846
  case "measureDom":
9835
9847
  case "fonts":
9836
9848
  this.parent.requestRedraw();
9837
9849
  break;
9838
9850
  case "fill":
9839
- this._updateTexture(0, value);
9840
- break;
9841
9851
  case "outline":
9842
- this._updateTexture(1, value);
9852
+ case "content":
9853
+ this._updateTextureMap();
9843
9854
  break;
9844
9855
  }
9845
9856
  }
9846
- async _updateTexture(index, fill) {
9847
- this._textures[index] = await this._loadTexture(fill);
9857
+ _update() {
9858
+ this.base.style = {
9859
+ justifyContent: "center",
9860
+ alignItems: "center",
9861
+ textAlign: "center",
9862
+ ...this.parent.style.toJSON()
9863
+ };
9864
+ this.base.update();
9865
+ }
9866
+ _updateTextureMap() {
9867
+ this._update();
9868
+ this._textureMap.clear();
9869
+ const pGlyphBoxs = [];
9870
+ this.base.paragraphs.forEach((p, pIndex) => {
9871
+ const fGlyphBoxs = [];
9872
+ p.fragments.forEach((f, fIndex) => {
9873
+ if (f.characters.length) {
9874
+ const fGlyphBox = BoundingBox.from(
9875
+ ...f.characters.map((c) => c.compatibleGlyphBox)
9876
+ );
9877
+ this._updateTexture(`${pIndex}.${fIndex}.fill`, f.fill, fGlyphBox);
9878
+ this._updateTexture(`${pIndex}.${fIndex}.outline`, f.outline, fGlyphBox);
9879
+ fGlyphBoxs.push(fGlyphBox);
9880
+ }
9881
+ });
9882
+ if (fGlyphBoxs.length) {
9883
+ const pGlyphBox = BoundingBox.from(...fGlyphBoxs);
9884
+ this._updateTexture(`${pIndex}.fill`, p.fill, pGlyphBox);
9885
+ this._updateTexture(`${pIndex}.outline`, p.outline, pGlyphBox);
9886
+ pGlyphBoxs.push(pGlyphBox);
9887
+ }
9888
+ });
9889
+ if (pGlyphBoxs.length) {
9890
+ const glyphBox = BoundingBox.from(...pGlyphBoxs);
9891
+ this._updateTexture("fill", this.fill, glyphBox);
9892
+ this._updateTexture("outline", this.outline, glyphBox);
9893
+ }
9848
9894
  this.parent.requestRedraw();
9849
9895
  }
9850
- async _loadTexture(fill) {
9896
+ async _updateTexture(key, fill, box) {
9897
+ if (fill && Object.keys(fill).length > 0) {
9898
+ this._textureMap.set(key, {
9899
+ texture: await this._loadTexture(fill, box),
9900
+ box
9901
+ });
9902
+ this.parent.requestRedraw();
9903
+ }
9904
+ }
9905
+ async _loadTexture(fill, box) {
9851
9906
  if (fill.linearGradient || fill.radialGradient) {
9852
9907
  return new GradientTexture(
9853
9908
  fill.linearGradient ?? fill.radialGradient,
9854
- this.parent.size.width,
9855
- this.parent.size.height
9909
+ box.width,
9910
+ box.height
9856
9911
  );
9857
9912
  } else if (!isNone(fill.image)) {
9858
9913
  this.parent.tree?.log(`load image ${fill.image}`);
@@ -9871,7 +9926,6 @@ class BaseElement2DText extends CoreObject {
9871
9926
  textAlign: "center",
9872
9927
  ...this.parent.style.toJSON()
9873
9928
  };
9874
- this.base.requestUpdate();
9875
9929
  return this.base.measure();
9876
9930
  }
9877
9931
  updateMeasure() {
@@ -9894,48 +9948,67 @@ class BaseElement2DText extends CoreObject {
9894
9948
  }
9895
9949
  draw() {
9896
9950
  const ctx = this.parent.context;
9897
- this.base.update();
9951
+ this._update();
9898
9952
  this.base.pathSets.forEach((pathSet) => {
9899
9953
  pathSet.paths.forEach((path) => {
9900
- if (path.style.stroke && !isNone(path.style.stroke)) {
9901
- if (typeof path.style.stroke === "object") {
9902
- const outline = path.style.stroke;
9903
- if (outline.enabled !== false && (this._textures[0] || outline.color) && (outline.width === void 0 || outline.width)) {
9904
- const { uvTransform, disableWrapMode } = getDrawOptions(outline, this.parent.size);
9954
+ const meta = path.getMeta();
9955
+ if (meta instanceof Character) {
9956
+ const fIndex = meta.parent.index;
9957
+ const pIndex = meta.parent.parent.index;
9958
+ if (path.style.fill && !isNone(path.style.fill)) {
9959
+ if (typeof path.style.fill === "object") {
9960
+ const fill = path.style.fill;
9961
+ const texture = this._textureMap.get(`${pIndex}.${fIndex}.fill`) ?? this._textureMap.get(`${pIndex}.fill`) ?? this._textureMap.get("fill");
9962
+ if (fill.enabled !== false && (texture || fill.color)) {
9963
+ const { uvTransform, disableWrapMode } = getDrawOptions(
9964
+ fill,
9965
+ texture?.box ?? {
9966
+ width: this.parent.size.width,
9967
+ height: this.parent.size.height
9968
+ }
9969
+ );
9970
+ ctx.addPath(path);
9971
+ ctx.style = { ...path.style };
9972
+ ctx.uvTransform = uvTransform;
9973
+ ctx.fillStyle = texture?.texture ?? fill.color;
9974
+ ctx.vertTransform = this._getVertTransform();
9975
+ ctx.fill({ disableWrapMode });
9976
+ }
9977
+ } else {
9905
9978
  ctx.addPath(path);
9906
9979
  ctx.style = { ...path.style };
9907
- ctx.lineWidth = outline.width || 1;
9908
- ctx.uvTransform = uvTransform;
9909
- ctx.strokeStyle = this._textures[0] ?? outline.color;
9910
- ctx.lineCap = outline.lineCap;
9911
- ctx.lineJoin = outline.lineJoin;
9912
9980
  ctx.vertTransform = this._getVertTransform();
9913
- ctx.stroke({ disableWrapMode });
9981
+ ctx.fill();
9914
9982
  }
9915
- } else {
9916
- ctx.addPath(path);
9917
- ctx.style = { ...path.style };
9918
- ctx.vertTransform = this._getVertTransform();
9919
- ctx.stroke();
9920
9983
  }
9921
- }
9922
- if (path.style.fill && !isNone(path.style.fill)) {
9923
- if (typeof path.style.fill === "object") {
9924
- const fill = path.style.fill;
9925
- if (fill.enabled !== false && (this._textures[1] || fill.color)) {
9926
- const { uvTransform, disableWrapMode } = getDrawOptions(fill, this.parent.size);
9984
+ if (path.style.stroke && !isNone(path.style.stroke)) {
9985
+ if (typeof path.style.stroke === "object") {
9986
+ const outline = path.style.stroke;
9987
+ const texture = this._textureMap.get(`${pIndex}.${fIndex}.outline`) ?? this._textureMap.get(`${pIndex}.outline`) ?? this._textureMap.get("outline");
9988
+ if (outline.enabled !== false && (texture || outline.color) && (outline.width === void 0 || outline.width)) {
9989
+ const { uvTransform, disableWrapMode } = getDrawOptions(
9990
+ outline,
9991
+ texture?.box ?? {
9992
+ width: this.parent.size.width,
9993
+ height: this.parent.size.height
9994
+ }
9995
+ );
9996
+ ctx.addPath(path);
9997
+ ctx.style = { ...path.style };
9998
+ ctx.lineWidth = outline.width || 1;
9999
+ ctx.uvTransform = uvTransform;
10000
+ ctx.strokeStyle = texture?.texture ?? outline.color;
10001
+ ctx.lineCap = outline.lineCap;
10002
+ ctx.lineJoin = outline.lineJoin;
10003
+ ctx.vertTransform = this._getVertTransform();
10004
+ ctx.stroke({ disableWrapMode });
10005
+ }
10006
+ } else {
9927
10007
  ctx.addPath(path);
9928
10008
  ctx.style = { ...path.style };
9929
- ctx.uvTransform = uvTransform;
9930
- ctx.fillStyle = this._textures[1] ?? fill.color;
9931
10009
  ctx.vertTransform = this._getVertTransform();
9932
- ctx.fill({ disableWrapMode });
10010
+ ctx.stroke();
9933
10011
  }
9934
- } else {
9935
- ctx.addPath(path);
9936
- ctx.style = { ...path.style };
9937
- ctx.vertTransform = this._getVertTransform();
9938
- ctx.fill();
9939
10012
  }
9940
10013
  }
9941
10014
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modern-canvas",
3
3
  "type": "module",
4
- "version": "0.8.5",
4
+ "version": "0.8.7",
5
5
  "packageManager": "pnpm@9.15.1",
6
6
  "description": "A JavaScript WebGL rendering engine.",
7
7
  "author": "wxm",
@@ -75,8 +75,8 @@
75
75
  "earcut": "^3.0.2",
76
76
  "modern-font": "^0.4.1",
77
77
  "modern-idoc": "^0.8.9",
78
- "modern-path2d": "^1.4.8",
79
- "modern-text": "^1.7.4"
78
+ "modern-path2d": "^1.4.9",
79
+ "modern-text": "^1.7.6"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@antfu/eslint-config": "^5.2.1",