composite method
Flattens layers onto target in descending Z-index order (topmost first).
Uses a bit-packed Uint32List occlusion map to prevent redundant writes and supports early exit if all destination cells are covered by opaque cells.
Implementation
void composite({
required Buffer target,
required List<LayeredBuffer> layers,
}) {
Tracer.record(_traceCompositeId, Phase.begin);
try {
if (layers.isEmpty) return;
// Stable sort in descending order (highest zIndex first)
final sortedLayers = List<LayeredBuffer>.from(layers);
sortedLayers.sort((a, b) => b.zIndex.compareTo(a.zIndex));
final totalCells = target.width * target.height;
final written = Uint32List((totalCells + 31) >> 5);
var remainingTargetCells = totalCells;
for (final layer in sortedLayers) {
if (remainingTargetCells <= 0) break; // Early exit: everything covered
final buf = layer.buffer;
final ox = layer.x;
final oy = layer.y;
for (var ly = 0; ly < buf.height; ly++) {
final ty = oy + ly;
if (ty < 0 || ty >= target.height) continue;
for (var lx = 0; lx < buf.width; lx++) {
final tx = ox + lx;
if (tx < 0 || tx >= target.width) continue;
final targetIdx = ty * target.width + tx;
final word = targetIdx >> 5;
final bit = targetIdx & 31;
if ((written[word] & (1 << bit)) != 0) {
continue; // Already covered by a higher layer
}
final sourceCell = buf.getCell(lx, ly);
if (sourceCell == null || sourceCell.isTransparent) continue;
final targetCell = target.cells[targetIdx];
targetCell.char = sourceCell.char;
targetCell.style = sourceCell.style;
written[word] |= (1 << bit);
remainingTargetCells--;
}
}
}
} finally {
Tracer.record(_traceCompositeId, Phase.end);
}
}