You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
const defaultValue = require("default-value");
|
|
|
|
const parser = require("../parser");
|
|
const findAlignment = require("../parser/find-alignment");
|
|
const generateStyle = require("../parser/generate-style");
|
|
const measureText = require("../render/measure-text");
|
|
const layoutItems = require("./layout-items");
|
|
const drawDebugLine = require("./draw-debug-line");
|
|
|
|
const sum = require("../util/sum");
|
|
const min = require("../util/min");
|
|
const max = require("../util/max");
|
|
const last = require("../util/last");
|
|
|
|
module.exports = function layoutFormattedText(text, options) {
|
|
let lines;
|
|
|
|
if (options.tags === true) {
|
|
lines = parser(text).map((lineItems) => {
|
|
return {
|
|
items: lineItems
|
|
};
|
|
});
|
|
} else {
|
|
lines = text.split("\n").map((line) => {
|
|
let lineMeasurements = measureText(line, options.defaultStyle);
|
|
|
|
return {
|
|
items: [{
|
|
text: line
|
|
}]
|
|
};
|
|
});
|
|
}
|
|
|
|
let processedLines = lines.map((line) => {
|
|
let processedItems = line.items.map((item) => {
|
|
let style;
|
|
|
|
if (item.tags != null) {
|
|
style = Object.assign({}, options.defaultStyle, generateStyle(item.tags, options.classes));
|
|
} else {
|
|
style = options.defaultStyle;
|
|
}
|
|
|
|
return Object.assign(item, {
|
|
style: style,
|
|
measurements: measureText(item.text, style)
|
|
});
|
|
});
|
|
|
|
let height = max(processedItems.map(item => item.measurements.height));
|
|
|
|
return Object.assign(line, {
|
|
alignment: defaultValue((line.items.length > 0) ? findAlignment(line.items[0]) : null, options.defaultStyle.alignment),
|
|
items: processedItems,
|
|
height: height,
|
|
adjustedHeight: height * options.lineHeight * 1.13,
|
|
width: sum(processedItems.map(item => item.measurements.width)),
|
|
minAscender: min(processedItems.map(item => item.measurements.ascender)),
|
|
maxDescender: max(processedItems.map(item => item.measurements.descender))
|
|
});
|
|
});
|
|
|
|
let startHeightCorrection, endHeightCorrection;
|
|
|
|
if (options.trimVerticalWhitespace) {
|
|
startHeightCorrection = -(lines[0].adjustedHeight / 2) - (lines[0].minAscender / 2);
|
|
endHeightCorrection = -(last(lines).adjustedHeight / 2) - (last(lines).minAscender / 2);
|
|
} else {
|
|
startHeightCorrection = 0;
|
|
endHeightCorrection = 0;
|
|
}
|
|
|
|
let totalTextWidth = Math.ceil(max(lines.map(line => line.width)));
|
|
|
|
let {positionedItems, debugLines} = layoutItems(lines, {
|
|
initialY: startHeightCorrection,
|
|
totalTextWidth: totalTextWidth
|
|
});
|
|
|
|
let combinedLineHeights = sum(lines.map(line => line.adjustedHeight));
|
|
|
|
return {
|
|
width: totalTextWidth,
|
|
height: Math.ceil(combinedLineHeights + startHeightCorrection + endHeightCorrection + last(lines).maxDescender),
|
|
items: positionedItems,
|
|
drawDebugLines: function drawDebugLines(context) {
|
|
debugLines.forEach((debugLine) => {
|
|
let width;
|
|
|
|
if (debugLine.x1 != null) {
|
|
width = [debugLine.x1, debugLine.x2];
|
|
} else {
|
|
width = this.width;
|
|
}
|
|
|
|
drawDebugLine(context, debugLine.lineNumber, debugLine.y, width, debugLine.color);
|
|
});
|
|
}
|
|
}
|
|
};
|