| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 | 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 isAlphabeticLetter(ch) {    var code = ch.charCodeAt(0);    return code >= 0x20 && code <= 0x24F        || code >= 0x370 && code <= 0x10FF        || code >= 0x1200 && code <= 0x13FF        || code >= 0x1E00 && code <= 0x206F;}var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) {    obj[ch] = true;    return obj;}, {});function isWordBreakChar(ch) {    if (isAlphabeticLetter(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    };}
 |