tex_break.dart
3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import 'nodes/space.dart';
import 'syntax_tree.dart';
extension SyntaxTreeTexStyleBreakExt on SyntaxTree {
/// Line breaking results using standard TeX-style line breaking.
///
/// This function will return a list of `SyntaxTree` along with a list
/// of line breaking penalties.
///
/// {@macro flutter_math_fork.widgets.math.tex_break}
BreakResult<SyntaxTree> texBreak({
int relPenalty = 500,
int binOpPenalty = 700,
bool enforceNoBreak = true,
}) {
final eqRowBreakResult = greenRoot.texBreak(
relPenalty: relPenalty,
binOpPenalty: binOpPenalty,
enforceNoBreak: true,
);
return BreakResult(
parts: eqRowBreakResult.parts
.map((part) => SyntaxTree(greenRoot: part))
.toList(growable: false),
penalties: eqRowBreakResult.penalties,
);
}
}
extension EquationRowNodeTexStyleBreakExt on EquationRowNode {
/// Line breaking results using standard TeX-style line breaking.
///
/// This function will return a list of `EquationRowNode` along with a list
/// of line breaking penalties.
///
/// {@macro flutter_math_fork.widgets.math.tex_break}
BreakResult<EquationRowNode> texBreak({
int relPenalty = 500,
int binOpPenalty = 700,
bool enforceNoBreak = true,
}) {
final breakIndices = <int>[];
final penalties = <int>[];
for (var i = 0; i < flattenedChildList.length; i++) {
final child = flattenedChildList[i];
// Peek ahead to see if the next child is a no-break
if (i < flattenedChildList.length - 1) {
final nextChild = flattenedChildList[i + 1];
if (nextChild is SpaceNode &&
nextChild.breakPenalty != null &&
nextChild.breakPenalty! >= 10000) {
if (!enforceNoBreak) {
// The break point should be moved to the next child, which is a \nobreak.
continue;
} else {
// In enforced mode, we should cancel the break point all together.
i++;
continue;
}
}
}
if (child.rightType == AtomType.bin) {
breakIndices.add(i);
penalties.add(binOpPenalty);
} else if (child.rightType == AtomType.rel) {
breakIndices.add(i);
penalties.add(relPenalty);
} else if (child is SpaceNode && child.breakPenalty != null) {
breakIndices.add(i);
penalties.add(child.breakPenalty!);
}
}
final res = <EquationRowNode>[];
var pos = 1;
for (var i = 0; i < breakIndices.length; i++) {
final breakEnd = caretPositions[breakIndices[i] + 1];
res.add(this.clipChildrenBetween(pos, breakEnd).wrapWithEquationRow());
pos = breakEnd;
}
if (pos != caretPositions.last) {
res.add(this
.clipChildrenBetween(pos, caretPositions.last)
.wrapWithEquationRow());
penalties.add(10000);
}
return BreakResult<EquationRowNode>(
parts: res,
penalties: penalties,
);
}
}
class BreakResult<T> {
final List<T> parts;
final List<int> penalties;
const BreakResult({
required this.parts,
required this.penalties,
});
}