parse.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. "use strict";
  2. exports.__esModule = true;
  3. var imageHelper = require("../../graphic/helper/image");
  4. var util_1 = require("../../core/util");
  5. var text_1 = require("../../contain/text");
  6. var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g;
  7. function truncateText(text, containerWidth, font, ellipsis, options) {
  8. if (!containerWidth) {
  9. return '';
  10. }
  11. var textLines = (text + '').split('\n');
  12. options = prepareTruncateOptions(containerWidth, font, ellipsis, options);
  13. for (var i = 0, len = textLines.length; i < len; i++) {
  14. textLines[i] = truncateSingleLine(textLines[i], options);
  15. }
  16. return textLines.join('\n');
  17. }
  18. exports.truncateText = truncateText;
  19. function prepareTruncateOptions(containerWidth, font, ellipsis, options) {
  20. options = options || {};
  21. var preparedOpts = util_1.extend({}, options);
  22. preparedOpts.font = font;
  23. ellipsis = util_1.retrieve2(ellipsis, '...');
  24. preparedOpts.maxIterations = util_1.retrieve2(options.maxIterations, 2);
  25. var minChar = preparedOpts.minChar = util_1.retrieve2(options.minChar, 0);
  26. preparedOpts.cnCharWidth = text_1.getWidth('国', font);
  27. var ascCharWidth = preparedOpts.ascCharWidth = text_1.getWidth('a', font);
  28. preparedOpts.placeholder = util_1.retrieve2(options.placeholder, '');
  29. var contentWidth = containerWidth = Math.max(0, containerWidth - 1);
  30. for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) {
  31. contentWidth -= ascCharWidth;
  32. }
  33. var ellipsisWidth = text_1.getWidth(ellipsis, font);
  34. if (ellipsisWidth > contentWidth) {
  35. ellipsis = '';
  36. ellipsisWidth = 0;
  37. }
  38. contentWidth = containerWidth - ellipsisWidth;
  39. preparedOpts.ellipsis = ellipsis;
  40. preparedOpts.ellipsisWidth = ellipsisWidth;
  41. preparedOpts.contentWidth = contentWidth;
  42. preparedOpts.containerWidth = containerWidth;
  43. return preparedOpts;
  44. }
  45. function truncateSingleLine(textLine, options) {
  46. var containerWidth = options.containerWidth;
  47. var font = options.font;
  48. var contentWidth = options.contentWidth;
  49. if (!containerWidth) {
  50. return '';
  51. }
  52. var lineWidth = text_1.getWidth(textLine, font);
  53. if (lineWidth <= containerWidth) {
  54. return textLine;
  55. }
  56. for (var j = 0;; j++) {
  57. if (lineWidth <= contentWidth || j >= options.maxIterations) {
  58. textLine += options.ellipsis;
  59. break;
  60. }
  61. var subLength = j === 0
  62. ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth)
  63. : lineWidth > 0
  64. ? Math.floor(textLine.length * contentWidth / lineWidth)
  65. : 0;
  66. textLine = textLine.substr(0, subLength);
  67. lineWidth = text_1.getWidth(textLine, font);
  68. }
  69. if (textLine === '') {
  70. textLine = options.placeholder;
  71. }
  72. return textLine;
  73. }
  74. function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) {
  75. var width = 0;
  76. var i = 0;
  77. for (var len = text.length; i < len && width < contentWidth; i++) {
  78. var charCode = text.charCodeAt(i);
  79. width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth;
  80. }
  81. return i;
  82. }
  83. function parsePlainText(text, font, padding, textLineHeight, truncate) {
  84. text != null && (text += '');
  85. var lineHeight = util_1.retrieve2(textLineHeight, text_1.getLineHeight(font));
  86. var lines = text ? text.split('\n') : [];
  87. var height = lines.length * lineHeight;
  88. var outerHeight = height;
  89. var canCacheByTextString = true;
  90. if (padding) {
  91. outerHeight += padding[0] + padding[2];
  92. }
  93. if (text && truncate) {
  94. canCacheByTextString = false;
  95. var truncOuterHeight = truncate.outerHeight;
  96. var truncOuterWidth = truncate.outerWidth;
  97. if (truncOuterHeight != null && outerHeight > truncOuterHeight) {
  98. text = '';
  99. lines = [];
  100. }
  101. else if (truncOuterWidth != null) {
  102. var options = prepareTruncateOptions(truncOuterWidth - (padding ? padding[1] + padding[3] : 0), font, truncate.ellipsis, {
  103. minChar: truncate.minChar,
  104. placeholder: truncate.placeholder
  105. });
  106. for (var i = 0, len = lines.length; i < len; i++) {
  107. lines[i] = truncateSingleLine(lines[i], options);
  108. }
  109. }
  110. }
  111. return {
  112. lines: lines,
  113. height: height,
  114. outerHeight: outerHeight,
  115. lineHeight: lineHeight,
  116. canCacheByTextString: canCacheByTextString
  117. };
  118. }
  119. exports.parsePlainText = parsePlainText;
  120. var RichTextToken = (function () {
  121. function RichTextToken() {
  122. }
  123. return RichTextToken;
  124. }());
  125. var RichTextLine = (function () {
  126. function RichTextLine(tokens) {
  127. this.tokens = [];
  128. if (tokens) {
  129. this.tokens = tokens;
  130. }
  131. }
  132. return RichTextLine;
  133. }());
  134. var RichTextContentBlock = (function () {
  135. function RichTextContentBlock() {
  136. this.width = 0;
  137. this.height = 0;
  138. this.outerWidth = 0;
  139. this.outerHeight = 0;
  140. this.lines = [];
  141. }
  142. return RichTextContentBlock;
  143. }());
  144. exports.RichTextContentBlock = RichTextContentBlock;
  145. function parseRichText(text, style) {
  146. var contentBlock = new RichTextContentBlock();
  147. text != null && (text += '');
  148. if (!text) {
  149. return contentBlock;
  150. }
  151. var lastIndex = STYLE_REG.lastIndex = 0;
  152. var result;
  153. while ((result = STYLE_REG.exec(text)) != null) {
  154. var matchedIndex = result.index;
  155. if (matchedIndex > lastIndex) {
  156. pushTokens(contentBlock, text.substring(lastIndex, matchedIndex));
  157. }
  158. pushTokens(contentBlock, result[2], result[1]);
  159. lastIndex = STYLE_REG.lastIndex;
  160. }
  161. if (lastIndex < text.length) {
  162. pushTokens(contentBlock, text.substring(lastIndex, text.length));
  163. }
  164. var lines = contentBlock.lines;
  165. var contentHeight = 0;
  166. var contentWidth = 0;
  167. var pendingList = [];
  168. var stlPadding = style.textPadding;
  169. var truncate = style.truncate;
  170. var truncateWidth = truncate && truncate.outerWidth;
  171. var truncateHeight = truncate && truncate.outerHeight;
  172. if (stlPadding) {
  173. truncateWidth != null && (truncateWidth -= stlPadding[1] + stlPadding[3]);
  174. truncateHeight != null && (truncateHeight -= stlPadding[0] + stlPadding[2]);
  175. }
  176. for (var i = 0; i < lines.length; i++) {
  177. var line = lines[i];
  178. var lineHeight = 0;
  179. var lineWidth = 0;
  180. for (var j = 0; j < line.tokens.length; j++) {
  181. var token = line.tokens[j];
  182. var tokenStyle = token.styleName && style.rich[token.styleName] || {};
  183. var textPadding = token.textPadding = tokenStyle.textPadding;
  184. var font = token.font = tokenStyle.font || style.font;
  185. var tokenHeight = token.textHeight = util_1.retrieve2(tokenStyle.textHeight, text_1.getLineHeight(font));
  186. textPadding && (tokenHeight += textPadding[0] + textPadding[2]);
  187. token.height = tokenHeight;
  188. token.lineHeight = util_1.retrieve3(tokenStyle.textLineHeight, style.textLineHeight, tokenHeight);
  189. token.textAlign = tokenStyle && tokenStyle.textAlign || style.textAlign;
  190. token.textVerticalAlign = tokenStyle && tokenStyle.textVerticalAlign || 'middle';
  191. if (truncateHeight != null && contentHeight + token.lineHeight > truncateHeight) {
  192. return new RichTextContentBlock();
  193. }
  194. token.textWidth = text_1.getWidth(token.text, font);
  195. var tokenWidth = tokenStyle.textWidth;
  196. var tokenWidthNotSpecified = tokenWidth == null || tokenWidth === 'auto';
  197. if (typeof tokenWidth === 'string' && tokenWidth.charAt(tokenWidth.length - 1) === '%') {
  198. token.percentWidth = tokenWidth;
  199. pendingList.push(token);
  200. tokenWidth = 0;
  201. }
  202. else {
  203. if (tokenWidthNotSpecified) {
  204. tokenWidth = token.textWidth;
  205. var textBackgroundColor = tokenStyle.textBackgroundColor;
  206. var bgImg = textBackgroundColor && textBackgroundColor.image;
  207. if (bgImg) {
  208. bgImg = imageHelper.findExistImage(bgImg);
  209. if (imageHelper.isImageReady(bgImg)) {
  210. tokenWidth = Math.max(tokenWidth, bgImg.width * tokenHeight / bgImg.height);
  211. }
  212. }
  213. }
  214. var paddingW = textPadding ? textPadding[1] + textPadding[3] : 0;
  215. tokenWidth += paddingW;
  216. var remianTruncWidth = truncateWidth != null ? truncateWidth - lineWidth : null;
  217. if (remianTruncWidth != null && remianTruncWidth < tokenWidth) {
  218. if (!tokenWidthNotSpecified || remianTruncWidth < paddingW) {
  219. token.text = '';
  220. token.textWidth = tokenWidth = 0;
  221. }
  222. else {
  223. token.text = truncateText(token.text, remianTruncWidth - paddingW, font, truncate.ellipsis, { minChar: truncate.minChar });
  224. token.textWidth = text_1.getWidth(token.text, font);
  225. tokenWidth = token.textWidth + paddingW;
  226. }
  227. }
  228. }
  229. lineWidth += (token.width = tokenWidth);
  230. tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight));
  231. }
  232. line.width = lineWidth;
  233. line.lineHeight = lineHeight;
  234. contentHeight += lineHeight;
  235. contentWidth = Math.max(contentWidth, lineWidth);
  236. }
  237. contentBlock.outerWidth = contentBlock.width = util_1.retrieve2(style.textWidth, contentWidth);
  238. contentBlock.outerHeight = contentBlock.height = util_1.retrieve2(style.textHeight, contentHeight);
  239. if (stlPadding) {
  240. contentBlock.outerWidth += stlPadding[1] + stlPadding[3];
  241. contentBlock.outerHeight += stlPadding[0] + stlPadding[2];
  242. }
  243. for (var i = 0; i < pendingList.length; i++) {
  244. var token = pendingList[i];
  245. var percentWidth = token.percentWidth;
  246. token.width = parseInt(percentWidth, 10) / 100 * contentWidth;
  247. }
  248. return contentBlock;
  249. }
  250. exports.parseRichText = parseRichText;
  251. function pushTokens(block, str, styleName) {
  252. var isEmptyStr = str === '';
  253. var strs = str.split('\n');
  254. var lines = block.lines;
  255. for (var i = 0; i < strs.length; i++) {
  256. var text = strs[i];
  257. var token = new RichTextToken();
  258. token.styleName = styleName;
  259. token.text = text;
  260. token.isLineHolder = !text && !isEmptyStr;
  261. if (!i) {
  262. var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens;
  263. var tokensLen = tokens.length;
  264. (tokensLen === 1 && tokens[0].isLineHolder)
  265. ? (tokens[0] = token)
  266. : ((text || !tokensLen || isEmptyStr) && tokens.push(token));
  267. }
  268. else {
  269. lines.push(new RichTextLine([token]));
  270. }
  271. }
  272. }
  273. //# sourceMappingURL=parse.js.map