| import * as imageHelper from '../helper/image.js'; | 
| import { extend, retrieve2, retrieve3, reduce } from '../../core/util.js'; | 
| import { getLineHeight, getWidth, parsePercent } from '../../contain/text.js'; | 
| var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; | 
| export function truncateText(text, containerWidth, font, ellipsis, options) { | 
|     if (!containerWidth) { | 
|         return ''; | 
|     } | 
|     var textLines = (text + '').split('\n'); | 
|     options = prepareTruncateOptions(containerWidth, font, ellipsis, options); | 
|     for (var i = 0, len = textLines.length; i < len; i++) { | 
|         textLines[i] = truncateSingleLine(textLines[i], options); | 
|     } | 
|     return textLines.join('\n'); | 
| } | 
| function prepareTruncateOptions(containerWidth, font, ellipsis, options) { | 
|     options = options || {}; | 
|     var preparedOpts = extend({}, options); | 
|     preparedOpts.font = font; | 
|     ellipsis = retrieve2(ellipsis, '...'); | 
|     preparedOpts.maxIterations = retrieve2(options.maxIterations, 2); | 
|     var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0); | 
|     preparedOpts.cnCharWidth = getWidth('国', font); | 
|     var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font); | 
|     preparedOpts.placeholder = retrieve2(options.placeholder, ''); | 
|     var contentWidth = containerWidth = Math.max(0, containerWidth - 1); | 
|     for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { | 
|         contentWidth -= ascCharWidth; | 
|     } | 
|     var ellipsisWidth = getWidth(ellipsis, font); | 
|     if (ellipsisWidth > contentWidth) { | 
|         ellipsis = ''; | 
|         ellipsisWidth = 0; | 
|     } | 
|     contentWidth = containerWidth - ellipsisWidth; | 
|     preparedOpts.ellipsis = ellipsis; | 
|     preparedOpts.ellipsisWidth = ellipsisWidth; | 
|     preparedOpts.contentWidth = contentWidth; | 
|     preparedOpts.containerWidth = containerWidth; | 
|     return preparedOpts; | 
| } | 
| function truncateSingleLine(textLine, options) { | 
|     var containerWidth = options.containerWidth; | 
|     var font = options.font; | 
|     var contentWidth = options.contentWidth; | 
|     if (!containerWidth) { | 
|         return ''; | 
|     } | 
|     var lineWidth = getWidth(textLine, font); | 
|     if (lineWidth <= containerWidth) { | 
|         return textLine; | 
|     } | 
|     for (var j = 0;; j++) { | 
|         if (lineWidth <= contentWidth || j >= options.maxIterations) { | 
|             textLine += options.ellipsis; | 
|             break; | 
|         } | 
|         var subLength = j === 0 | 
|             ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) | 
|             : lineWidth > 0 | 
|                 ? Math.floor(textLine.length * contentWidth / lineWidth) | 
|                 : 0; | 
|         textLine = textLine.substr(0, subLength); | 
|         lineWidth = getWidth(textLine, font); | 
|     } | 
|     if (textLine === '') { | 
|         textLine = options.placeholder; | 
|     } | 
|     return textLine; | 
| } | 
| function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { | 
|     var width = 0; | 
|     var i = 0; | 
|     for (var len = text.length; i < len && width < contentWidth; i++) { | 
|         var charCode = text.charCodeAt(i); | 
|         width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth; | 
|     } | 
|     return i; | 
| } | 
| export function parsePlainText(text, style) { | 
|     text != null && (text += ''); | 
|     var overflow = style.overflow; | 
|     var padding = style.padding; | 
|     var font = style.font; | 
|     var truncate = overflow === 'truncate'; | 
|     var calculatedLineHeight = getLineHeight(font); | 
|     var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight); | 
|     var bgColorDrawn = !!(style.backgroundColor); | 
|     var truncateLineOverflow = style.lineOverflow === 'truncate'; | 
|     var width = style.width; | 
|     var lines; | 
|     if (width != null && (overflow === 'break' || overflow === 'breakAll')) { | 
|         lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : []; | 
|     } | 
|     else { | 
|         lines = text ? text.split('\n') : []; | 
|     } | 
|     var contentHeight = lines.length * lineHeight; | 
|     var height = retrieve2(style.height, contentHeight); | 
|     if (contentHeight > height && truncateLineOverflow) { | 
|         var lineCount = Math.floor(height / lineHeight); | 
|         lines = lines.slice(0, lineCount); | 
|     } | 
|     if (text && truncate && width != null) { | 
|         var options = prepareTruncateOptions(width, font, style.ellipsis, { | 
|             minChar: style.truncateMinChar, | 
|             placeholder: style.placeholder | 
|         }); | 
|         for (var i = 0; i < lines.length; i++) { | 
|             lines[i] = truncateSingleLine(lines[i], options); | 
|         } | 
|     } | 
|     var outerHeight = height; | 
|     var contentWidth = 0; | 
|     for (var i = 0; i < lines.length; i++) { | 
|         contentWidth = Math.max(getWidth(lines[i], font), contentWidth); | 
|     } | 
|     if (width == null) { | 
|         width = contentWidth; | 
|     } | 
|     var outerWidth = contentWidth; | 
|     if (padding) { | 
|         outerHeight += padding[0] + padding[2]; | 
|         outerWidth += padding[1] + padding[3]; | 
|         width += padding[1] + padding[3]; | 
|     } | 
|     if (bgColorDrawn) { | 
|         outerWidth = width; | 
|     } | 
|     return { | 
|         lines: lines, | 
|         height: height, | 
|         outerWidth: outerWidth, | 
|         outerHeight: outerHeight, | 
|         lineHeight: lineHeight, | 
|         calculatedLineHeight: calculatedLineHeight, | 
|         contentWidth: contentWidth, | 
|         contentHeight: contentHeight, | 
|         width: width | 
|     }; | 
| } | 
| var RichTextToken = (function () { | 
|     function RichTextToken() { | 
|     } | 
|     return RichTextToken; | 
| }()); | 
| var RichTextLine = (function () { | 
|     function RichTextLine(tokens) { | 
|         this.tokens = []; | 
|         if (tokens) { | 
|             this.tokens = tokens; | 
|         } | 
|     } | 
|     return RichTextLine; | 
| }()); | 
| var RichTextContentBlock = (function () { | 
|     function RichTextContentBlock() { | 
|         this.width = 0; | 
|         this.height = 0; | 
|         this.contentWidth = 0; | 
|         this.contentHeight = 0; | 
|         this.outerWidth = 0; | 
|         this.outerHeight = 0; | 
|         this.lines = []; | 
|     } | 
|     return RichTextContentBlock; | 
| }()); | 
| export { RichTextContentBlock }; | 
| export function parseRichText(text, style) { | 
|     var contentBlock = new RichTextContentBlock(); | 
|     text != null && (text += ''); | 
|     if (!text) { | 
|         return contentBlock; | 
|     } | 
|     var topWidth = style.width; | 
|     var topHeight = style.height; | 
|     var overflow = style.overflow; | 
|     var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null | 
|         ? { width: topWidth, accumWidth: 0, breakAll: overflow === 'breakAll' } | 
|         : null; | 
|     var lastIndex = STYLE_REG.lastIndex = 0; | 
|     var result; | 
|     while ((result = STYLE_REG.exec(text)) != null) { | 
|         var matchedIndex = result.index; | 
|         if (matchedIndex > lastIndex) { | 
|             pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo); | 
|         } | 
|         pushTokens(contentBlock, result[2], style, wrapInfo, result[1]); | 
|         lastIndex = STYLE_REG.lastIndex; | 
|     } | 
|     if (lastIndex < text.length) { | 
|         pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo); | 
|     } | 
|     var pendingList = []; | 
|     var calculatedHeight = 0; | 
|     var calculatedWidth = 0; | 
|     var stlPadding = style.padding; | 
|     var truncate = overflow === 'truncate'; | 
|     var truncateLine = style.lineOverflow === 'truncate'; | 
|     function finishLine(line, lineWidth, lineHeight) { | 
|         line.width = lineWidth; | 
|         line.lineHeight = lineHeight; | 
|         calculatedHeight += lineHeight; | 
|         calculatedWidth = Math.max(calculatedWidth, lineWidth); | 
|     } | 
|     outer: for (var i = 0; i < contentBlock.lines.length; i++) { | 
|         var line = contentBlock.lines[i]; | 
|         var lineHeight = 0; | 
|         var lineWidth = 0; | 
|         for (var j = 0; j < line.tokens.length; j++) { | 
|             var token = line.tokens[j]; | 
|             var tokenStyle = token.styleName && style.rich[token.styleName] || {}; | 
|             var textPadding = token.textPadding = tokenStyle.padding; | 
|             var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0; | 
|             var font = token.font = tokenStyle.font || style.font; | 
|             token.contentHeight = getLineHeight(font); | 
|             var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight); | 
|             token.innerHeight = tokenHeight; | 
|             textPadding && (tokenHeight += textPadding[0] + textPadding[2]); | 
|             token.height = tokenHeight; | 
|             token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight); | 
|             token.align = tokenStyle && tokenStyle.align || style.align; | 
|             token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle'; | 
|             if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) { | 
|                 if (j > 0) { | 
|                     line.tokens = line.tokens.slice(0, j); | 
|                     finishLine(line, lineWidth, lineHeight); | 
|                     contentBlock.lines = contentBlock.lines.slice(0, i + 1); | 
|                 } | 
|                 else { | 
|                     contentBlock.lines = contentBlock.lines.slice(0, i); | 
|                 } | 
|                 break outer; | 
|             } | 
|             var styleTokenWidth = tokenStyle.width; | 
|             var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto'; | 
|             if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') { | 
|                 token.percentWidth = styleTokenWidth; | 
|                 pendingList.push(token); | 
|                 token.contentWidth = getWidth(token.text, font); | 
|             } | 
|             else { | 
|                 if (tokenWidthNotSpecified) { | 
|                     var textBackgroundColor = tokenStyle.backgroundColor; | 
|                     var bgImg = textBackgroundColor && textBackgroundColor.image; | 
|                     if (bgImg) { | 
|                         bgImg = imageHelper.findExistImage(bgImg); | 
|                         if (imageHelper.isImageReady(bgImg)) { | 
|                             token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height); | 
|                         } | 
|                     } | 
|                 } | 
|                 var remainTruncWidth = truncate && topWidth != null | 
|                     ? topWidth - lineWidth : null; | 
|                 if (remainTruncWidth != null && remainTruncWidth < token.width) { | 
|                     if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) { | 
|                         token.text = ''; | 
|                         token.width = token.contentWidth = 0; | 
|                     } | 
|                     else { | 
|                         token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, { minChar: style.truncateMinChar }); | 
|                         token.width = token.contentWidth = getWidth(token.text, font); | 
|                     } | 
|                 } | 
|                 else { | 
|                     token.contentWidth = getWidth(token.text, font); | 
|                 } | 
|             } | 
|             token.width += paddingH; | 
|             lineWidth += token.width; | 
|             tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); | 
|         } | 
|         finishLine(line, lineWidth, lineHeight); | 
|     } | 
|     contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth); | 
|     contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight); | 
|     contentBlock.contentHeight = calculatedHeight; | 
|     contentBlock.contentWidth = calculatedWidth; | 
|     if (stlPadding) { | 
|         contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; | 
|         contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; | 
|     } | 
|     for (var i = 0; i < pendingList.length; i++) { | 
|         var token = pendingList[i]; | 
|         var percentWidth = token.percentWidth; | 
|         token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width; | 
|     } | 
|     return contentBlock; | 
| } | 
| function pushTokens(block, str, style, wrapInfo, styleName) { | 
|     var isEmptyStr = str === ''; | 
|     var tokenStyle = styleName && style.rich[styleName] || {}; | 
|     var lines = block.lines; | 
|     var font = tokenStyle.font || style.font; | 
|     var newLine = false; | 
|     var strLines; | 
|     var linesWidths; | 
|     if (wrapInfo) { | 
|         var tokenPadding = tokenStyle.padding; | 
|         var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0; | 
|         if (tokenStyle.width != null && tokenStyle.width !== 'auto') { | 
|             var outerWidth_1 = parsePercent(tokenStyle.width, wrapInfo.width) + tokenPaddingH; | 
|             if (lines.length > 0) { | 
|                 if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) { | 
|                     strLines = str.split('\n'); | 
|                     newLine = true; | 
|                 } | 
|             } | 
|             wrapInfo.accumWidth = outerWidth_1; | 
|         } | 
|         else { | 
|             var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth); | 
|             wrapInfo.accumWidth = res.accumWidth + tokenPaddingH; | 
|             linesWidths = res.linesWidths; | 
|             strLines = res.lines; | 
|         } | 
|     } | 
|     else { | 
|         strLines = str.split('\n'); | 
|     } | 
|     for (var i = 0; i < strLines.length; i++) { | 
|         var text = strLines[i]; | 
|         var token = new RichTextToken(); | 
|         token.styleName = styleName; | 
|         token.text = text; | 
|         token.isLineHolder = !text && !isEmptyStr; | 
|         if (typeof tokenStyle.width === 'number') { | 
|             token.width = tokenStyle.width; | 
|         } | 
|         else { | 
|             token.width = linesWidths | 
|                 ? linesWidths[i] | 
|                 : getWidth(text, font); | 
|         } | 
|         if (!i && !newLine) { | 
|             var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens; | 
|             var tokensLen = tokens.length; | 
|             (tokensLen === 1 && tokens[0].isLineHolder) | 
|                 ? (tokens[0] = token) | 
|                 : ((text || !tokensLen || isEmptyStr) && tokens.push(token)); | 
|         } | 
|         else { | 
|             lines.push(new RichTextLine([token])); | 
|         } | 
|     } | 
| } | 
| function isLatin(ch) { | 
|     var code = ch.charCodeAt(0); | 
|     return code >= 0x21 && code <= 0x17F; | 
| } | 
| var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) { | 
|     obj[ch] = true; | 
|     return obj; | 
| }, {}); | 
| function isWordBreakChar(ch) { | 
|     if (isLatin(ch)) { | 
|         if (breakCharMap[ch]) { | 
|             return true; | 
|         } | 
|         return false; | 
|     } | 
|     return true; | 
| } | 
| function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) { | 
|     var lines = []; | 
|     var linesWidths = []; | 
|     var line = ''; | 
|     var currentWord = ''; | 
|     var currentWordWidth = 0; | 
|     var accumWidth = 0; | 
|     for (var i = 0; i < text.length; i++) { | 
|         var ch = text.charAt(i); | 
|         if (ch === '\n') { | 
|             if (currentWord) { | 
|                 line += currentWord; | 
|                 accumWidth += currentWordWidth; | 
|             } | 
|             lines.push(line); | 
|             linesWidths.push(accumWidth); | 
|             line = ''; | 
|             currentWord = ''; | 
|             currentWordWidth = 0; | 
|             accumWidth = 0; | 
|             continue; | 
|         } | 
|         var chWidth = getWidth(ch, font); | 
|         var inWord = isBreakAll ? false : !isWordBreakChar(ch); | 
|         if (!lines.length | 
|             ? lastAccumWidth + accumWidth + chWidth > lineWidth | 
|             : accumWidth + chWidth > lineWidth) { | 
|             if (!accumWidth) { | 
|                 if (inWord) { | 
|                     lines.push(currentWord); | 
|                     linesWidths.push(currentWordWidth); | 
|                     currentWord = ch; | 
|                     currentWordWidth = chWidth; | 
|                 } | 
|                 else { | 
|                     lines.push(ch); | 
|                     linesWidths.push(chWidth); | 
|                 } | 
|             } | 
|             else if (line || currentWord) { | 
|                 if (inWord) { | 
|                     if (!line) { | 
|                         line = currentWord; | 
|                         currentWord = ''; | 
|                         currentWordWidth = 0; | 
|                         accumWidth = currentWordWidth; | 
|                     } | 
|                     lines.push(line); | 
|                     linesWidths.push(accumWidth - currentWordWidth); | 
|                     currentWord += ch; | 
|                     currentWordWidth += chWidth; | 
|                     line = ''; | 
|                     accumWidth = currentWordWidth; | 
|                 } | 
|                 else { | 
|                     if (currentWord) { | 
|                         line += currentWord; | 
|                         currentWord = ''; | 
|                         currentWordWidth = 0; | 
|                     } | 
|                     lines.push(line); | 
|                     linesWidths.push(accumWidth); | 
|                     line = ch; | 
|                     accumWidth = chWidth; | 
|                 } | 
|             } | 
|             continue; | 
|         } | 
|         accumWidth += chWidth; | 
|         if (inWord) { | 
|             currentWord += ch; | 
|             currentWordWidth += chWidth; | 
|         } | 
|         else { | 
|             if (currentWord) { | 
|                 line += currentWord; | 
|                 currentWord = ''; | 
|                 currentWordWidth = 0; | 
|             } | 
|             line += ch; | 
|         } | 
|     } | 
|     if (!lines.length && !line) { | 
|         line = text; | 
|         currentWord = ''; | 
|         currentWordWidth = 0; | 
|     } | 
|     if (currentWord) { | 
|         line += currentWord; | 
|     } | 
|     if (line) { | 
|         lines.push(line); | 
|         linesWidths.push(accumWidth); | 
|     } | 
|     if (lines.length === 1) { | 
|         accumWidth += lastAccumWidth; | 
|     } | 
|     return { | 
|         accumWidth: accumWidth, | 
|         lines: lines, | 
|         linesWidths: linesWidths | 
|     }; | 
| } |