@leafer-ui/node 1.0.0-rc.5 → 1.0.0-rc.6

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/node.esm.js CHANGED
@@ -1,9 +1,42 @@
1
- import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, BoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, Creator, LeaferCanvasBase, canvasPatch, LeaferImage, InteractionBase, MatrixHelper, ImageEvent, PointHelper, MathHelper, TaskProcessor } from '@leafer/core';
1
+ import { LeafList, DataHelper, RenderEvent, ChildEvent, WatchEvent, PropertyEvent, LeafHelper, BranchHelper, Bounds, LeafBoundsHelper, BoundsHelper, Debug, LeafLevelList, LayoutEvent, Run, ImageManager, Platform, AnimateEvent, ResizeEvent, Creator, LeaferCanvasBase, canvasPatch, LeaferImage, InteractionBase, FileHelper, MatrixHelper, ImageEvent, PointHelper, MathHelper, TaskProcessor } from '@leafer/core';
2
2
  export * from '@leafer/core';
3
3
  export { LeaferImage } from '@leafer/core';
4
+ import { writeFileSync } from 'fs';
4
5
  import { ColorConvert as ColorConvert$1, ImageManager as ImageManager$1, Paint, Effect, TextConvert as TextConvert$1, Export as Export$1 } from '@leafer-ui/core';
5
6
  export * from '@leafer-ui/core';
6
7
 
8
+ /******************************************************************************
9
+ Copyright (c) Microsoft Corporation.
10
+
11
+ Permission to use, copy, modify, and/or distribute this software for any
12
+ purpose with or without fee is hereby granted.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
15
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20
+ PERFORMANCE OF THIS SOFTWARE.
21
+ ***************************************************************************** */
22
+ /* global Reflect, Promise, SuppressedError, Symbol */
23
+
24
+
25
+ function __awaiter(thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ }
34
+
35
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
36
+ var e = new Error(message);
37
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
38
+ };
39
+
7
40
  class Watcher {
8
41
  get childrenChanged() { return this.hasAdd || this.hasRemove || this.hasVisible; }
9
42
  get updatedList() {
@@ -558,7 +591,7 @@ class Renderer {
558
591
  }
559
592
 
560
593
  const { hitRadiusPoint } = BoundsHelper;
561
- class FindPath {
594
+ class Pather {
562
595
  constructor(target, selector) {
563
596
  this.target = target;
564
597
  this.selector = selector;
@@ -678,117 +711,108 @@ class FindPath {
678
711
  class Selector {
679
712
  constructor(target, userConfig) {
680
713
  this.config = {};
681
- this.innerIdList = {};
682
- this.idList = {};
683
- this.classNameList = {};
684
- this.tagNameList = {};
714
+ this.innerIdMap = {};
715
+ this.idMap = {};
716
+ this.methods = {
717
+ id: (leaf, name) => leaf.id === name ? this.idMap[name] = leaf : 0,
718
+ innerId: (leaf, innerId) => leaf.innerId === innerId ? this.innerIdMap[innerId] = leaf : 0,
719
+ className: (leaf, name) => leaf.className === name ? 1 : 0,
720
+ tag: (leaf, name) => leaf.__tag === name ? 1 : 0
721
+ };
685
722
  this.target = target;
686
723
  if (userConfig)
687
724
  this.config = DataHelper.default(userConfig, this.config);
688
- this.findPath = new FindPath(target, this);
725
+ this.pather = new Pather(target, this);
689
726
  this.__listenEvents();
690
727
  }
691
728
  getByPoint(hitPoint, hitRadius, options) {
692
729
  if (Platform.name === 'node')
693
730
  this.target.emit(LayoutEvent.CHECK_UPDATE);
694
- return this.findPath.getByPoint(hitPoint, hitRadius, options);
695
- }
696
- find(name, branch) {
697
- if (typeof name === 'number') {
698
- return this.getByInnerId(name, branch);
699
- }
700
- else if (name.startsWith('#')) {
701
- return this.getById(name.substring(1), branch);
702
- }
703
- else if (name.startsWith('.')) {
704
- return this.getByClassName(name.substring(1), branch);
705
- }
706
- else {
707
- return this.getByTagName(name, branch);
731
+ return this.pather.getByPoint(hitPoint, hitRadius, options);
732
+ }
733
+ getBy(condition, branch, one, options) {
734
+ switch (typeof condition) {
735
+ case 'number':
736
+ const leaf = this.getByInnerId(condition, branch);
737
+ return one ? leaf : (leaf ? [leaf] : []);
738
+ case 'string':
739
+ switch (condition[0]) {
740
+ case '#':
741
+ const leaf = this.getById(condition.substring(1), branch);
742
+ return one ? leaf : (leaf ? [leaf] : []);
743
+ case '.':
744
+ return this.getByMethod(this.methods.className, branch, one, condition.substring(1));
745
+ default:
746
+ return this.getByMethod(this.methods.tag, branch, one, condition);
747
+ }
748
+ case 'function':
749
+ return this.getByMethod(condition, branch, one, options);
708
750
  }
709
751
  }
710
- getByInnerId(name, branch) {
711
- let cache = this.innerIdList[name];
752
+ getByInnerId(innerId, branch) {
753
+ const cache = this.innerIdMap[innerId];
712
754
  if (cache)
713
755
  return cache;
714
- if (!branch)
715
- branch = this.target;
716
- let find;
717
- this.loopFind(branch, (leaf) => {
718
- if (leaf.innerId === name) {
719
- find = leaf;
720
- this.innerIdList[name] = find;
721
- return true;
722
- }
723
- else {
724
- return false;
725
- }
726
- });
727
- return find;
756
+ this.eachFind(this.toChildren(branch), this.methods.innerId, null, innerId);
757
+ return this.findLeaf;
728
758
  }
729
- getById(name, branch) {
730
- let cache = this.idList[name];
731
- if (cache)
759
+ getById(id, branch) {
760
+ const cache = this.idMap[id];
761
+ if (cache && LeafHelper.hasParent(cache, branch || this.target))
732
762
  return cache;
733
- if (!branch)
734
- branch = this.target;
735
- let find;
736
- this.loopFind(branch, (leaf) => {
737
- if (leaf.id === name) {
738
- find = leaf;
739
- this.idList[name] = find;
740
- return true;
741
- }
742
- else {
743
- return false;
744
- }
745
- });
746
- return find;
747
- }
748
- getByClassName(name, branch) {
749
- if (!branch)
750
- branch = this.target;
751
- let find = [];
752
- this.loopFind(branch, (leaf) => {
753
- if (leaf.className === name)
754
- find.push(leaf);
755
- return false;
756
- });
757
- return find;
758
- }
759
- getByTagName(name, branch) {
760
- if (!branch)
761
- branch = this.target;
762
- let find = [];
763
- this.loopFind(branch, (leaf) => {
764
- if (leaf.__tag === name)
765
- find.push(leaf);
766
- return false;
767
- });
768
- return find;
763
+ this.eachFind(this.toChildren(branch), this.methods.id, null, id);
764
+ return this.findLeaf;
769
765
  }
770
- loopFind(branch, find) {
771
- if (find(branch))
772
- return;
773
- const { children } = branch;
766
+ getByClassName(className, branch) {
767
+ return this.getByMethod(this.methods.className, branch, false, className);
768
+ }
769
+ getByTag(tag, branch) {
770
+ return this.getByMethod(this.methods.tag, branch, false, tag);
771
+ }
772
+ getByMethod(method, branch, one, options) {
773
+ const list = one ? null : [];
774
+ this.eachFind(this.toChildren(branch), method, list, options);
775
+ return list || this.findLeaf;
776
+ }
777
+ eachFind(children, method, list, options) {
778
+ let child;
774
779
  for (let i = 0, len = children.length; i < len; i++) {
775
- branch = children[i];
776
- if (find(branch))
777
- return;
778
- if (branch.isBranch)
779
- this.loopFind(branch, find);
780
+ child = children[i];
781
+ if (method(child, options)) {
782
+ if (list) {
783
+ list.push(child);
784
+ }
785
+ else {
786
+ this.findLeaf = child;
787
+ return;
788
+ }
789
+ }
790
+ if (child.isBranch)
791
+ this.eachFind(child.children, method, list, options);
780
792
  }
781
793
  }
794
+ toChildren(branch) {
795
+ this.findLeaf = null;
796
+ return [branch || this.target];
797
+ }
782
798
  __onRemoveChild(event) {
783
- const target = event.target;
784
- if (this.idList[target.id])
785
- this.idList[target.id] = null;
786
- if (this.innerIdList[target.id])
787
- this.innerIdList[target.innerId] = null;
799
+ const { id, innerId } = event.child;
800
+ if (this.idMap[id])
801
+ delete this.idMap[id];
802
+ if (this.innerIdMap[innerId])
803
+ delete this.innerIdMap[innerId];
804
+ }
805
+ __checkIdChange(event) {
806
+ if (event.attrName === 'id') {
807
+ const id = event.oldValue;
808
+ if (this.idMap[id])
809
+ delete this.idMap[id];
810
+ }
788
811
  }
789
812
  __listenEvents() {
790
813
  this.__eventIds = [
791
- this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
814
+ this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this),
815
+ this.target.on_(PropertyEvent.CHANGE, this.__checkIdChange, this)
792
816
  ];
793
817
  }
794
818
  __removeListenEvents() {
@@ -798,11 +822,10 @@ class Selector {
798
822
  destroy() {
799
823
  if (this.__eventIds.length) {
800
824
  this.__removeListenEvents();
801
- this.findPath.destroy();
802
- this.innerIdList = {};
803
- this.idList = {};
804
- this.classNameList = {};
805
- this.tagNameList = {};
825
+ this.pather.destroy();
826
+ this.findLeaf = null;
827
+ this.innerIdMap = {};
828
+ this.idMap = {};
806
829
  }
807
830
  }
808
831
  }
@@ -821,8 +844,10 @@ class LeaferCanvas extends LeaferCanvasBase {
821
844
  this.__createView();
822
845
  this.__createContext();
823
846
  this.resize(this.config);
824
- this.context.__proto__.roundRect = null;
825
- canvasPatch(this.context.__proto__);
847
+ if (Platform.roundRectPatch) {
848
+ this.context.__proto__.roundRect = null;
849
+ canvasPatch(this.context.__proto__);
850
+ }
826
851
  }
827
852
  __createView() {
828
853
  this.view = Platform.origin.createCanvas(1, 1);
@@ -835,6 +860,7 @@ class LeaferCanvas extends LeaferCanvasBase {
835
860
  }
836
861
  }
837
862
 
863
+ const { mineType, fileType } = FileHelper;
838
864
  Object.assign(Creator, {
839
865
  canvas: (options, manager) => new LeaferCanvas(options, manager),
840
866
  image: (options) => new LeaferImage(options),
@@ -842,6 +868,7 @@ Object.assign(Creator, {
842
868
  interaction: (target, canvas, selector, options) => { return new InteractionBase(target, canvas, selector, options); }
843
869
  });
844
870
  function useCanvas(canvasType, power) {
871
+ Platform.canvasType = canvasType;
845
872
  if (!Platform.origin) {
846
873
  if (canvasType === 'skia') {
847
874
  const { Canvas, loadImage } = power;
@@ -852,7 +879,19 @@ function useCanvas(canvasType, power) {
852
879
  canvasSaveAs: (canvas, filename, quality) => canvas.saveAs(filename, { quality }),
853
880
  loadImage
854
881
  };
882
+ Platform.roundRectPatch = true;
883
+ }
884
+ else if (canvasType === 'napi') {
885
+ const { Canvas, loadImage } = power;
886
+ Platform.origin = {
887
+ createCanvas: (width, height, format) => new Canvas(width, height, format),
888
+ canvasToDataURL: (canvas, type, quality) => canvas.toDataURL(mineType(type), quality),
889
+ canvasToBolb: (canvas, type, quality) => __awaiter(this, void 0, void 0, function* () { return canvas.toBuffer(mineType(type), quality); }),
890
+ canvasSaveAs: (canvas, filename, quality) => __awaiter(this, void 0, void 0, function* () { return writeFileSync(filename, canvas.toBuffer(mineType(fileType(filename)), quality)); }),
891
+ loadImage
892
+ };
855
893
  }
894
+ Platform.ellipseToCurve = true;
856
895
  Platform.event = {
857
896
  stopDefault(_origin) { },
858
897
  stopNow(_origin) { },
@@ -1013,38 +1052,6 @@ function emit(type, data) {
1013
1052
  data.target.emitEvent(new ImageEvent(type, data));
1014
1053
  }
1015
1054
 
1016
- /******************************************************************************
1017
- Copyright (c) Microsoft Corporation.
1018
-
1019
- Permission to use, copy, modify, and/or distribute this software for any
1020
- purpose with or without fee is hereby granted.
1021
-
1022
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1023
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1024
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1025
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1026
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1027
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1028
- PERFORMANCE OF THIS SOFTWARE.
1029
- ***************************************************************************** */
1030
- /* global Reflect, Promise, SuppressedError, Symbol */
1031
-
1032
-
1033
- function __awaiter(thisArg, _arguments, P, generator) {
1034
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1035
- return new (P || (P = Promise))(function (resolve, reject) {
1036
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1037
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
1038
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1039
- step((generator = generator.apply(thisArg, _arguments || [])).next());
1040
- });
1041
- }
1042
-
1043
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1044
- var e = new Error(message);
1045
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1046
- };
1047
-
1048
1055
  const { get: get$2, scale: scaleHelper, copy: copy$1 } = MatrixHelper;
1049
1056
  function createPattern(ui, paint, pixelRatio) {
1050
1057
  let { scaleX, scaleY } = ui.__world;
@@ -1146,8 +1153,9 @@ function checkImage(ui, canvas, paint, allowPaint) {
1146
1153
  if (!paint.patternTask) {
1147
1154
  paint.patternTask = ImageManager.patternTasker.add(() => __awaiter(this, void 0, void 0, function* () {
1148
1155
  paint.patternTask = null;
1149
- if (canvas.bounds.hit(ui.__world) && createPattern(ui, paint, canvas.pixelRatio))
1150
- ui.forceUpdate('surface');
1156
+ if (canvas.bounds.hit(ui.__world))
1157
+ createPattern(ui, paint, canvas.pixelRatio);
1158
+ ui.forceUpdate('surface');
1151
1159
  }), 300);
1152
1160
  }
1153
1161
  }
@@ -1811,6 +1819,8 @@ function createRows(drawData, content, style) {
1811
1819
  const { width, height } = bounds;
1812
1820
  const charMode = width || height || __letterSpacing || (textCase !== 'none');
1813
1821
  if (charMode) {
1822
+ const wrap = style.textWrap !== 'none';
1823
+ const breakAll = style.textWrap === 'break';
1814
1824
  paraStart = true;
1815
1825
  lastCharType = null;
1816
1826
  startCharSize = charWidth = charSize = wordWidth = rowWidth = 0;
@@ -1837,16 +1847,23 @@ function createRows(drawData, content, style) {
1837
1847
  langBreak = (charType === Single && (lastCharType === Single || lastCharType === Letter)) || (lastCharType === Single && charType !== After);
1838
1848
  afterBreak = ((charType === Before || charType === Single) && (lastCharType === Symbol || lastCharType === After));
1839
1849
  realWidth = paraStart && paraIndent ? width - paraIndent : width;
1840
- if (width && rowWidth + wordWidth + charWidth > realWidth) {
1841
- if (!afterBreak)
1842
- afterBreak = charType === Letter && lastCharType == After;
1843
- if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
1850
+ if (wrap && (width && rowWidth + wordWidth + charWidth > realWidth)) {
1851
+ if (breakAll) {
1844
1852
  if (wordWidth)
1845
1853
  addWord();
1846
1854
  addRow();
1847
1855
  }
1848
1856
  else {
1849
- addRow();
1857
+ if (!afterBreak)
1858
+ afterBreak = charType === Letter && lastCharType == After;
1859
+ if (langBreak || afterBreak || charType === Break || charType === Before || charType === Single || (wordWidth + charWidth > realWidth)) {
1860
+ if (wordWidth)
1861
+ addWord();
1862
+ addRow();
1863
+ }
1864
+ else {
1865
+ addRow();
1866
+ }
1850
1867
  }
1851
1868
  }
1852
1869
  if (char === ' ' && paraStart !== true && (rowWidth + wordWidth) === 0) ;
@@ -1916,7 +1933,7 @@ function addRow() {
1916
1933
 
1917
1934
  const CharMode = 0;
1918
1935
  const WordMode = 1;
1919
- const RowMode = 2;
1936
+ const TextMode = 2;
1920
1937
  function layoutChar(drawData, style, width, _height) {
1921
1938
  const { rows } = drawData;
1922
1939
  const { textAlign, paraIndent, letterSpacing } = style;
@@ -1925,15 +1942,12 @@ function layoutChar(drawData, style, width, _height) {
1925
1942
  if (row.words) {
1926
1943
  indentWidth = paraIndent && row.paraStart ? paraIndent : 0;
1927
1944
  addWordWidth = (width && textAlign === 'justify' && row.words.length > 1) ? (width - row.width - indentWidth) / (row.words.length - 1) : 0;
1928
- mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : RowMode);
1929
- if (mode === RowMode) {
1930
- row.text = '';
1945
+ mode = (letterSpacing || row.isOverflow) ? CharMode : (addWordWidth > 0.01 ? WordMode : TextMode);
1946
+ if (row.isOverflow && !letterSpacing)
1947
+ row.textMode = true;
1948
+ if (mode === TextMode) {
1931
1949
  row.x += indentWidth;
1932
- row.words.forEach(word => {
1933
- word.data.forEach(char => {
1934
- row.text += char.char;
1935
- });
1936
- });
1950
+ toTextChar$1(row);
1937
1951
  }
1938
1952
  else {
1939
1953
  row.x += indentWidth;
@@ -1959,6 +1973,14 @@ function layoutChar(drawData, style, width, _height) {
1959
1973
  }
1960
1974
  });
1961
1975
  }
1976
+ function toTextChar$1(row) {
1977
+ row.text = '';
1978
+ row.words.forEach(word => {
1979
+ word.data.forEach(char => {
1980
+ row.text += char.char;
1981
+ });
1982
+ });
1983
+ }
1962
1984
  function toWordChar(data, charX, wordChar) {
1963
1985
  data.forEach(char => {
1964
1986
  wordChar.char += char.char;
@@ -1979,10 +2001,10 @@ function toChar(data, charX, rowData) {
1979
2001
 
1980
2002
  function layoutText(drawData, style) {
1981
2003
  const { rows, bounds } = drawData;
1982
- const { __lineHeight, __baseLine, __letterSpacing, textAlign, verticalAlign, paraSpacing, textOverflow } = style;
2004
+ const { __lineHeight, __baseLine, __letterSpacing, __clipText, textAlign, verticalAlign, paraSpacing } = style;
1983
2005
  let { x, y, width, height } = bounds, realHeight = __lineHeight * rows.length + (paraSpacing ? paraSpacing * (drawData.paraNumber - 1) : 0);
1984
2006
  let starY = __baseLine;
1985
- if (textOverflow !== 'show' && realHeight > height) {
2007
+ if (__clipText && realHeight > height) {
1986
2008
  realHeight = Math.max(height, __lineHeight);
1987
2009
  drawData.overflow = rows.length;
1988
2010
  }
@@ -2031,39 +2053,58 @@ function layoutText(drawData, style) {
2031
2053
  bounds.x = rowX;
2032
2054
  if (rowWidth > bounds.width)
2033
2055
  bounds.width = rowWidth;
2056
+ if (__clipText && width && width < rowWidth) {
2057
+ row.isOverflow = true;
2058
+ if (!drawData.overflow)
2059
+ drawData.overflow = rows.length;
2060
+ }
2034
2061
  }
2035
2062
  bounds.y = y;
2036
2063
  bounds.height = realHeight;
2037
2064
  }
2038
2065
 
2039
- function clipText(drawData, textOverflow) {
2066
+ function clipText(drawData, style) {
2040
2067
  const { rows, overflow } = drawData;
2068
+ let { textOverflow } = style;
2041
2069
  rows.splice(overflow);
2042
2070
  if (textOverflow !== 'hide') {
2043
2071
  if (textOverflow === 'ellipsis')
2044
2072
  textOverflow = '...';
2073
+ let char, charRight;
2045
2074
  const ellipsisWidth = Platform.canvas.measureText(textOverflow).width;
2046
- const row = rows[overflow - 1];
2047
- let char, end = row.data.length - 1, charRight;
2048
- const { x, width } = drawData.bounds;
2049
- const right = x + width - ellipsisWidth;
2050
- for (let i = end; i > -1; i--) {
2051
- char = row.data[i];
2052
- charRight = char.x + char.width;
2053
- if (i === end && charRight < right) {
2054
- break;
2055
- }
2056
- else if (charRight < right && char.char !== ' ') {
2057
- row.data.splice(i + 1);
2058
- row.width -= char.width;
2059
- break;
2075
+ const right = style.x + style.width - ellipsisWidth;
2076
+ const list = style.textWrap === 'none' ? rows : [rows[overflow - 1]];
2077
+ list.forEach(row => {
2078
+ if (row.isOverflow && row.data) {
2079
+ let end = row.data.length - 1;
2080
+ for (let i = end; i > -1; i--) {
2081
+ char = row.data[i];
2082
+ charRight = char.x + char.width;
2083
+ if (i === end && charRight < right) {
2084
+ break;
2085
+ }
2086
+ else if (charRight < right && char.char !== ' ') {
2087
+ row.data.splice(i + 1);
2088
+ row.width -= char.width;
2089
+ break;
2090
+ }
2091
+ row.width -= char.width;
2092
+ }
2093
+ row.width += ellipsisWidth;
2094
+ row.data.push({ char: textOverflow, x: charRight });
2095
+ if (row.textMode)
2096
+ toTextChar(row);
2060
2097
  }
2061
- row.width -= char.width;
2062
- }
2063
- row.width += ellipsisWidth;
2064
- row.data.push({ char: textOverflow, x: charRight });
2098
+ });
2065
2099
  }
2066
2100
  }
2101
+ function toTextChar(row) {
2102
+ row.text = '';
2103
+ row.data.forEach(char => {
2104
+ row.text += char.char;
2105
+ });
2106
+ row.data = null;
2107
+ }
2067
2108
 
2068
2109
  function decorationText(drawData, style) {
2069
2110
  const { fontSize } = style;
@@ -2084,7 +2125,7 @@ const TextConvert = {
2084
2125
  let x = 0, y = 0;
2085
2126
  let width = style.__getInput('width') || 0;
2086
2127
  let height = style.__getInput('height') || 0;
2087
- const { textDecoration, textOverflow, __font, padding } = style;
2128
+ const { textDecoration, __font, padding } = style;
2088
2129
  if (padding) {
2089
2130
  const [top, right, bottom, left] = MathHelper.fourNumber(padding);
2090
2131
  if (width) {
@@ -2106,7 +2147,7 @@ const TextConvert = {
2106
2147
  layoutText(drawData, style);
2107
2148
  layoutChar(drawData, style, width);
2108
2149
  if (drawData.overflow)
2109
- clipText(drawData, textOverflow);
2150
+ clipText(drawData, style);
2110
2151
  if (textDecoration !== 'none')
2111
2152
  decorationText(drawData, style);
2112
2153
  return drawData;