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

'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);
});
}
}
};