UNPKG

@visactor/vtable

Version:

canvas table width high performance

167 lines (148 loc) 7.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.measureTextBounds = exports.restoreMeasureText = exports.setCustomAlphabetCharSet = exports.textMeasure = exports.TextMeasureTool = exports.FastTextMeasureContribution = exports.initTextMeasure = void 0; const vrender_1 = require("./../../vrender"), vutils_1 = require("@visactor/vutils"); let customAlphabetCharSet = "", textMeasureMode = "quick"; const textMeasureModule = new vrender_1.ContainerModule(((bind, unbind, isBound, rebind) => { isBound(vrender_1.TextMeasureContribution) ? rebind(vrender_1.TextMeasureContribution).to(FastTextMeasureContribution).inSingletonScope() : bind(vrender_1.TextMeasureContribution).to(FastTextMeasureContribution).inSingletonScope(); })), restoreTextMeasureModule = new vrender_1.ContainerModule(((bind, unbind, isBound, rebind) => { isBound(vrender_1.TextMeasureContribution) ? rebind(vrender_1.TextMeasureContribution).to(vrender_1.DefaultTextMeasureContribution).inSingletonScope() : bind(vrender_1.TextMeasureContribution).to(vrender_1.DefaultTextMeasureContribution).inSingletonScope(); })); exports.default = textMeasureModule; const initTextMeasure = (textSpec, option, useNaiveCanvas) => new vutils_1.TextMeasure(Object.assign({ defaultFontParams: { fontFamily: vrender_1.DefaultTextStyle.fontFamily, fontSize: vrender_1.DefaultTextStyle.fontSize }, getTextBounds: useNaiveCanvas ? void 0 : vrender_1.getTextBounds, specialCharSet: `{}()//&-/: .,@%'"~…=——${vutils_1.TextMeasure.ALPHABET_CHAR_SET}${vutils_1.TextMeasure.ALPHABET_CHAR_SET.toUpperCase()}0123456789${customAlphabetCharSet}` }, null != option ? option : {}), textSpec); exports.initTextMeasure = initTextMeasure; const fastTextMeasureCache = new Map; function getFastTextMeasure(fontSize, fontWeight, fontFamily, fontStyle = "normal") { const key = `${fontSize}-${fontWeight}-${fontFamily}-${fontStyle}`, cache = fastTextMeasureCache.get(key); if (cache) return cache; const fastTextMeasure = (0, exports.initTextMeasure)({ fontSize: fontSize, fontFamily: fontFamily, fontWeight: fontWeight, fontStyle: fontStyle }); return fastTextMeasureCache.set(key, fastTextMeasure), fastTextMeasure; } class FastTextMeasureContribution extends vrender_1.DefaultTextMeasureContribution { _fastMeasure(text, options) { const {fontSize: fontSize, fontFamily: fontFamily = "Arial,sans-serif", fontWeight: fontWeight = "normal", fontStyle: fontStyle = "normal"} = options, textMeasure = getFastTextMeasure(fontSize, fontWeight, fontFamily, fontStyle).measure(text, textMeasureMode); if (!(0, vutils_1.isValid)(textMeasure.fontBoundingBoxAscent) && !(0, vutils_1.isValid)(textMeasure.fontBoundingBoxDescent)) { const {ascent: ascent, descent: descent} = this.measureTextBoundADscentEstimate(options); textMeasure.fontBoundingBoxAscent = ascent, textMeasure.fontBoundingBoxDescent = descent; } return textMeasure; } measureTextWidth(text, options) { return this._fastMeasure(text, options).width; } measureText(text, options) { return this._fastMeasure(text, options); } _measureTextWithoutAlignBaseline(text, options, compatible) { return this._fastMeasure(text, options); } _measureTextWithAlignBaseline(text, options, compatible) { return this._fastMeasure(text, options); } } exports.FastTextMeasureContribution = FastTextMeasureContribution; class TextMeasureTool { measureText(text, options) { const {fontSize: fontSize, fontFamily: fontFamily = "Arial,sans-serif", fontWeight: fontWeight = "normal", fontStyle: fontStyle = "normal"} = options; return getFastTextMeasure(fontSize, fontWeight, fontFamily, fontStyle).measure(text, textMeasureMode); } measureTextWidth(text, options) { const {fontSize: fontSize, fontFamily: fontFamily = "Arial,sans-serif", fontWeight: fontWeight = "normal", fontStyle: fontStyle = "normal"} = options; return getFastTextMeasure(fontSize, fontWeight, fontFamily, fontStyle).measure(text, textMeasureMode).width; } clipText(text, options, width) { if (0 === text.length) return { str: "", width: 0 }; let length = this.measureTextWidth(text, options); return length <= width ? { str: text, width: length } : (length = this.measureTextWidth(text[0], options), length > width ? { str: "", width: 0 } : this._clipText(text, options, width, 0, text.length - 1)); } _clipText(text, options, width, leftIdx, rightIdx) { const middleIdx = Math.floor((leftIdx + rightIdx) / 2), subText = text.substring(0, middleIdx + 1), strWidth = this.measureTextWidth(subText, options); let length; if (strWidth > width) { if (subText.length <= 1) return { str: "", width: 0 }; const str = text.substring(0, middleIdx); return length = this.measureTextWidth(str, options), length <= width ? { str: str, width: length } : this._clipText(text, options, width, leftIdx, middleIdx); } if (strWidth < width) { if (middleIdx >= text.length - 1) return { str: text, width: this.measureTextWidth(text, options) }; const str = text.substring(0, middleIdx + 2); return length = this.measureTextWidth(str, options), length >= width ? { str: subText, width: strWidth } : this._clipText(text, options, width, middleIdx, rightIdx); } return { str: subText, width: strWidth }; } clipTextWithSuffix(text, options, width, suffix) { if ("" === suffix) return this.clipText(text, options, width); if (0 === text.length) return { str: "", width: 0 }; const length = this.measureTextWidth(text, options); if (length <= width) return { str: text, width: length }; const suffixWidth = this.measureTextWidth(suffix, options); if (suffixWidth > width) return { str: "", width: 0 }; width -= suffixWidth; const data = this._clipText(text, options, width, 0, text.length - 1); return data.str += suffix, data.width += suffixWidth, data; } } function setCustomAlphabetCharSet(str) { customAlphabetCharSet = str, fastTextMeasureCache.clear(); } function restoreMeasureText() { textMeasureMode = "canvas", vrender_1.container.load(restoreTextMeasureModule); } exports.TextMeasureTool = TextMeasureTool, exports.textMeasure = new TextMeasureTool, exports.setCustomAlphabetCharSet = setCustomAlphabetCharSet, exports.restoreMeasureText = restoreMeasureText; const utilTextMark = new vrender_1.Text({ ignoreBuf: !0 }); function measureTextBounds(attribute) { return utilTextMark.initAttributes(Object.assign(Object.assign({}, attribute), { ignoreBuf: !0 })), utilTextMark.AABBBounds; } exports.measureTextBounds = measureTextBounds; //# sourceMappingURL=text-measure.js.map