molstar
Version:
A comprehensive macromolecular library.
284 lines • 14.8 kB
JavaScript
"use strict";
/**
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextBuilder = void 0;
var tslib_1 = require("tslib");
var param_definition_1 = require("../../../mol-util/param-definition");
var util_1 = require("../../../mol-data/util");
var text_1 = require("./text");
var font_atlas_1 = require("./font-atlas");
var quadIndices = new Uint16Array([
0, 1, 2,
1, 3, 2
]);
// avoiding namespace lookup improved performance in Chrome (Aug 2020)
var caAdd3 = util_1.ChunkedArray.add3;
var caAdd2 = util_1.ChunkedArray.add2;
var caAdd = util_1.ChunkedArray.add;
var TextBuilder;
(function (TextBuilder) {
function create(props, initialCount, chunkSize, text) {
if (props === void 0) { props = {}; }
if (initialCount === void 0) { initialCount = 2048; }
if (chunkSize === void 0) { chunkSize = 1024; }
initialCount *= 2;
chunkSize *= 2;
var centers = util_1.ChunkedArray.create(Float32Array, 3, chunkSize, text ? text.centerBuffer.ref.value : initialCount);
var mappings = util_1.ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.mappingBuffer.ref.value : initialCount);
var depths = util_1.ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.depthBuffer.ref.value : initialCount);
var indices = util_1.ChunkedArray.create(Uint32Array, 3, chunkSize, text ? text.indexBuffer.ref.value : initialCount);
var groups = util_1.ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.groupBuffer.ref.value : initialCount);
var tcoords = util_1.ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.tcoordBuffer.ref.value : initialCount);
var p = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, param_definition_1.ParamDefinition.getDefaultValues(text_1.Text.Params)), props);
var attachment = p.attachment, background = p.background, backgroundMargin = p.backgroundMargin, tether = p.tether, tetherLength = p.tetherLength, tetherBaseWidth = p.tetherBaseWidth;
var fontAtlas = (0, font_atlas_1.getFontAtlas)(p);
var margin = (1 / 2.5) * backgroundMargin;
var outline = fontAtlas.buffer / fontAtlas.lineHeight;
var add = function (x, y, z, depth, group) {
caAdd3(centers, x, y, z);
caAdd(depths, depth);
caAdd(groups, group);
};
return {
add: function (str, x, y, z, depth, scale, group) {
var bWidth = 0;
var nChar = str.length;
// calculate width
for (var iChar = 0; iChar < nChar; ++iChar) {
var c = fontAtlas.get(str[iChar]);
bWidth += c.nw - 2 * outline;
}
var bHeight = 1 / 1.25;
// attachment
var yShift, xShift;
// vertical
if (attachment.startsWith('top')) {
yShift = bHeight;
}
else if (attachment.startsWith('middle')) {
yShift = bHeight / 2;
}
else {
yShift = 0; // "bottom"
}
// horizontal
if (attachment.endsWith('right')) {
xShift = bWidth;
}
else if (attachment.endsWith('center')) {
xShift = bWidth / 2;
}
else {
xShift = 0; // "left"
}
if (tether) {
switch (attachment) {
case 'bottom-left':
xShift -= tetherLength / 2 + margin + 0.1;
yShift -= tetherLength / 2 + margin;
break;
case 'bottom-center':
yShift -= tetherLength + margin;
break;
case 'bottom-right':
xShift += tetherLength / 2 + margin + 0.1;
yShift -= tetherLength / 2 + margin;
break;
case 'middle-left':
xShift -= tetherLength + margin + 0.1;
break;
case 'middle-center':
break;
case 'middle-right':
xShift += tetherLength + margin + 0.1;
break;
case 'top-left':
xShift -= tetherLength / 2 + margin + 0.1;
yShift += tetherLength / 2 + margin;
break;
case 'top-center':
yShift += tetherLength + margin;
break;
case 'top-right':
xShift += tetherLength / 2 + margin + 0.1;
yShift += tetherLength / 2 + margin;
break;
}
}
var xLeft = (-xShift - margin - 0.1) * scale;
var xRight = (bWidth - xShift + margin + 0.1) * scale;
var yTop = (bHeight - yShift + margin) * scale;
var yBottom = (-yShift - margin) * scale;
// background
if (background) {
caAdd2(mappings, xLeft, yTop); // top left
caAdd2(mappings, xLeft, yBottom); // bottom left
caAdd2(mappings, xRight, yTop); // top right
caAdd2(mappings, xRight, yBottom); // bottom right
var offset = centers.elementCount;
for (var i = 0; i < 4; ++i) {
caAdd2(tcoords, 10, 10);
add(x, y, z, depth, group);
}
caAdd3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]);
caAdd3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]);
}
if (tether) {
var xTip = void 0, yTip = void 0;
var xBaseA = void 0, yBaseA = void 0;
var xBaseB = void 0, yBaseB = void 0;
var xBaseCenter = void 0, yBaseCenter = void 0;
var scaledTetherLength = tetherLength * scale;
var scaledTetherBaseWidth = tetherBaseWidth * scale;
switch (attachment) {
case 'bottom-left':
xTip = xLeft - scaledTetherLength / 2;
xBaseA = xLeft + scaledTetherBaseWidth / 2;
xBaseB = xLeft;
xBaseCenter = xLeft;
yTip = yBottom - scaledTetherLength / 2;
yBaseA = yBottom;
yBaseB = yBottom + scaledTetherBaseWidth / 2;
yBaseCenter = yBottom;
break;
case 'bottom-center':
xTip = 0;
xBaseA = scaledTetherBaseWidth / 2;
xBaseB = -scaledTetherBaseWidth / 2;
xBaseCenter = 0;
yTip = yBottom - scaledTetherLength;
yBaseA = yBottom;
yBaseB = yBottom;
yBaseCenter = yBottom;
break;
case 'bottom-right':
xTip = xRight + scaledTetherLength / 2;
xBaseA = xRight;
xBaseB = xRight - scaledTetherBaseWidth / 2;
xBaseCenter = xRight;
yTip = yBottom - scaledTetherLength / 2;
yBaseA = yBottom + scaledTetherBaseWidth / 2;
yBaseB = yBottom;
yBaseCenter = yBottom;
break;
case 'middle-left':
xTip = xLeft - scaledTetherLength;
xBaseA = xLeft;
xBaseB = xLeft;
xBaseCenter = xLeft;
yTip = 0;
yBaseA = -scaledTetherBaseWidth / 2;
yBaseB = scaledTetherBaseWidth / 2;
yBaseCenter = 0;
break;
case 'middle-center':
xTip = 0;
xBaseA = 0;
xBaseB = 0;
xBaseCenter = 0;
yTip = 0;
yBaseA = 0;
yBaseB = 0;
yBaseCenter = 0;
break;
case 'middle-right':
xTip = xRight + scaledTetherLength;
xBaseA = xRight;
xBaseB = xRight;
xBaseCenter = xRight;
yTip = 0;
yBaseA = scaledTetherBaseWidth / 2;
yBaseB = -scaledTetherBaseWidth / 2;
yBaseCenter = 0;
break;
case 'top-left':
xTip = xLeft - scaledTetherLength / 2;
xBaseA = xLeft + scaledTetherBaseWidth / 2;
xBaseB = xLeft;
xBaseCenter = xLeft;
yTip = yTop + scaledTetherLength / 2;
yBaseA = yTop;
yBaseB = yTop - scaledTetherBaseWidth / 2;
yBaseCenter = yTop;
break;
case 'top-center':
xTip = 0;
xBaseA = scaledTetherBaseWidth / 2;
xBaseB = -scaledTetherBaseWidth / 2;
xBaseCenter = 0;
yTip = yTop + scaledTetherLength;
yBaseA = yTop;
yBaseB = yTop;
yBaseCenter = yTop;
break;
case 'top-right':
xTip = xRight + scaledTetherLength / 2;
xBaseA = xRight;
xBaseB = xRight - scaledTetherBaseWidth / 2;
xBaseCenter = xRight;
yTip = yTop + scaledTetherLength / 2;
yBaseA = yTop - scaledTetherBaseWidth / 2;
yBaseB = yTop;
yBaseCenter = yTop;
break;
default:
throw new Error('unsupported attachment');
}
caAdd2(mappings, xTip, yTip); // tip
caAdd2(mappings, xBaseA, yBaseA); // base A
caAdd2(mappings, xBaseB, yBaseB); // base B
caAdd2(mappings, xBaseCenter, yBaseCenter); // base center
var offset = centers.elementCount;
for (var i = 0; i < 4; ++i) {
caAdd2(tcoords, 10, 10);
add(x, y, z, depth, group);
}
caAdd3(indices, offset, offset + 1, offset + 3);
caAdd3(indices, offset, offset + 3, offset + 2);
}
xShift += outline;
yShift += outline;
var xadvance = 0;
for (var iChar = 0; iChar < nChar; ++iChar) {
var c = fontAtlas.get(str[iChar]);
var left = (xadvance - xShift) * scale;
var right = (xadvance + c.nw - xShift) * scale;
var top_1 = (c.nh - yShift) * scale;
var bottom = (-yShift) * scale;
caAdd2(mappings, left, top_1);
caAdd2(mappings, left, bottom);
caAdd2(mappings, right, top_1);
caAdd2(mappings, right, bottom);
var texWidth = fontAtlas.texture.width;
var texHeight = fontAtlas.texture.height;
caAdd2(tcoords, c.x / texWidth, c.y / texHeight); // top left
caAdd2(tcoords, c.x / texWidth, (c.y + c.h) / texHeight); // bottom left
caAdd2(tcoords, (c.x + c.w) / texWidth, c.y / texHeight); // top right
caAdd2(tcoords, (c.x + c.w) / texWidth, (c.y + c.h) / texHeight); // bottom right
xadvance += c.nw - 2 * outline;
var offset = centers.elementCount;
for (var i = 0; i < 4; ++i)
add(x, y, z, depth, group);
caAdd3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]);
caAdd3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]);
}
},
getText: function () {
var ft = fontAtlas.texture;
var cb = util_1.ChunkedArray.compact(centers, true);
var mb = util_1.ChunkedArray.compact(mappings, true);
var db = util_1.ChunkedArray.compact(depths, true);
var ib = util_1.ChunkedArray.compact(indices, true);
var gb = util_1.ChunkedArray.compact(groups, true);
var tb = util_1.ChunkedArray.compact(tcoords, true);
return text_1.Text.create(ft, cb, mb, db, ib, gb, tb, indices.elementCount / 2, text);
}
};
}
TextBuilder.create = create;
})(TextBuilder = exports.TextBuilder || (exports.TextBuilder = {}));
//# sourceMappingURL=text-builder.js.map