@visactor/vtable
Version:
canvas table width high performance
167 lines (148 loc) • 7.41 kB
JavaScript
;
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