in packages/charts/src/chart_types/partition_chart/layout/viewmodel/fill_text_layout.ts [296:417]
function tryFontSize<C>(
measure: TextMeasure,
rotation: Radian,
verticalAlignment: VerticalAlignments,
horizontalAlignment: HorizontalAlignment,
container: C,
getShapeRowGeometry: GetShapeRowGeometry<C>,
cx: Coordinate,
cy: Coordinate,
padding: Padding,
node: ShapeTreeNode,
boxes: Box[],
maxRowCount: number,
clipText: boolean,
isRTL: boolean,
) {
const adjustedHorizontalAlignment = isRTL ? getOppositeAlignment(horizontalAlignment) : horizontalAlignment;
return function tryFontSizeFn(initialRowSet: RowSet, fontSize: Pixels): { rowSet: RowSet; completed: boolean } {
let rowSet: RowSet = initialRowSet;
const wordSpacing = getWordSpacing(fontSize);
// model text pieces, obtaining their width at the current font size
const allMeasuredBoxes = boxes.map<RowBox>((box) => {
const { width } = measure(box.text, box, fontSize);
return {
width,
wordBeginning: NaN,
...box,
fontSize, // iterated fontSize overrides a possible more global fontSize
};
});
const linePitch = fontSize;
// rowSet building starts
let targetRowCount = 0;
let measuredBoxes = allMeasuredBoxes.slice();
let innerCompleted = false;
// iterate through possible target row counts
while (++targetRowCount <= maxRowCount && !innerCompleted) {
measuredBoxes = allMeasuredBoxes.slice();
rowSet = {
id: nodeId(node),
fontSize,
fillTextColor: '',
rotation,
verticalAlignment,
horizontalAlignment: adjustedHorizontalAlignment,
clipText,
isRTL,
rows: [...new Array(targetRowCount)].map(() => ({
rowWords: [],
rowAnchorX: NaN,
rowAnchorY: NaN,
maximumLength: NaN,
length: NaN,
})),
container,
};
let currentRowIndex = 0;
// iterate through rows
while (currentRowIndex < targetRowCount) {
const currentRow = rowSet.rows[currentRowIndex];
if (!currentRow) {
currentRowIndex++;
continue;
}
const currentRowWords = currentRow.rowWords;
// current row geometries
const { maximumRowLength, rowAnchorX, rowAnchorY } = getShapeRowGeometry(
container,
cx,
cy,
targetRowCount,
linePitch,
currentRowIndex,
fontSize,
rotation,
verticalAlignment,
padding,
);
currentRow.rowAnchorX = rowAnchorX;
currentRow.rowAnchorY = rowAnchorY;
currentRow.maximumLength = maximumRowLength;
// row building starts
let currentRowLength = 0;
let rowHasRoom = true;
// iterate through words: keep adding words while there's room
while (measuredBoxes.length > 0 && rowHasRoom) {
// adding box to row
const [currentBox] = measuredBoxes;
if (!currentBox) continue;
const wordBeginning = currentRowLength;
currentRowLength += currentBox.width + wordSpacing;
if (clipText || currentRowLength <= currentRow.maximumLength) {
currentRowWords.push({ ...currentBox, wordBeginning });
currentRow.length = currentRowLength;
measuredBoxes.shift();
} else {
rowHasRoom = false;
}
}
currentRowIndex++;
}
innerCompleted = rowSetComplete(rowSet, measuredBoxes);
}
const completed = measuredBoxes.length === 0;
return { rowSet, completed };
};
}