crampedText function
Text under root whose glyphs come within vertical pixels of the top
or bottom, or horizontal pixels of the sides, of the smallest
hand-drawn border around it, or spill past it. The defaults are
kWiredInkPadding, the space every skribble control keeps.
Gaps are measured in the content's own size, so a scaled-down preview is judged by its proportions; text and ink hidden by scrolling or clips are ignored.
Ink wobbles and has width, so a gap that is fine for a straight CSS border looks cramped here: these minimums are measured from the ideal edge, before the pen.
Implementation
List<CrampedText> crampedText(
RenderObject root, {
double? vertical,
double? horizontal,
}) {
final minimumVertical = vertical ?? kWiredInkPadding.top;
final minimumHorizontal = horizontal ?? kWiredInkPadding.left;
final borders = _borders(root);
final cramped = <CrampedText>[];
for (final (text, bounds, uncut, scale) in _texts(root)) {
Rect? border;
var whole = Rect.zero;
var owner = '?';
for (final (candidate, name, uncut) in borders) {
// The text lives in a border when most of it is inside; a neighbour
// straddling the line belongs to something else.
final inside = candidate.intersect(bounds);
if (inside.width <= 0 ||
inside.height <= 0 ||
inside.width * inside.height < bounds.width * bounds.height / 2) {
continue;
}
// The smallest border around the text is the one it lives in.
if (border == null ||
candidate.width * candidate.height < border.width * border.height) {
border = candidate;
whole = uncut;
owner = name;
}
}
// Badges and other micro labels keep their own tight pill; text that
// lives in one is not measured against the larger shape around it.
if (border == null || border.shortestSide <= 24) continue;
// A side a clip has cut off, of the ink or of the text, shows nothing
// to crowd.
double gap(double value, {required bool cut}) =>
cut ? double.infinity : value / scale;
final gaps = EdgeInsets.fromLTRB(
gap(
bounds.left - border.left,
cut: border.left > whole.left + .5 || bounds.left > uncut.left + .5,
),
gap(
bounds.top - border.top,
cut: border.top > whole.top + .5 || bounds.top > uncut.top + .5,
),
gap(
border.right - bounds.right,
cut: border.right < whole.right - .5 || bounds.right < uncut.right - .5,
),
gap(
border.bottom - bounds.bottom,
cut:
border.bottom < whole.bottom - .5 ||
bounds.bottom < uncut.bottom - .5,
),
);
// Half a pixel of slack absorbs glyph side bearings and rounding.
if (math.min(gaps.top, gaps.bottom) < minimumVertical - .5 ||
math.min(gaps.left, gaps.right) < minimumHorizontal - .5) {
cramped.add(CrampedText(text, border, gaps, owner));
}
}
return cramped;
}