Penalty. rule: Break Rule- Module
- std.
typeset - Receiver
- Penalty
- Minimum arity
- 0
- Maximum arity
- 0
Declaration and parameters
LinkAvailability
Included by default: Pending
Import std.typeset in language mode 5.21.
The current compiler selects std/typeset.tpz for this language mode. Availability in other released editions and inclusion in each installed distribution are Pending.
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
b48527d0a174· 21 - compiler/crates/topaz_resolve/src/stdlib.rs at
b48527d0a174· 40
Receiver
Penalty
Parameter constraints
Penalty.unitEnd is the exclusive end of a measured unit span. It must be greater than zero and no greater than the paragraph unit count. The penalty's position in the Item array does not set that boundary.
Planning collects penalties and visits them in increasing unitEnd order. Equal endpoints retain input order. Duplicate endpoints remain separate candidates and are counted separately in breakOpportunityCount.
Penalty.rule determines whether a candidate is selectable and how its additional cost is interpreted. Forbidden removes that candidate. A selectable duplicate at the same endpoint remains available. A Forced entry prevents any line from crossing that boundary.
Penalty.kind describes the selected boundary independently of its rule. For example a Forced rule can carry a LatinHyphen kind. The chosen line reports the selected candidate's kind.
Penalty.width is a nonnegative Length<Pt> that contributes when that candidate ends a line. Both cost models include this width for every kind. Unselected candidates contribute no width.
PlanLine.selectedPenaltyWidth reports that selected width separately from the measured text widths. Input penalty widths are validated even for Forbidden candidates.
Penalty.flagged marks a break for KnuthPlassPolicy.flaggedDemerit and finalFlaggedDemerit. FixedPoint does not use this flag. Its consecutive soft hyphen rule depends on kind.
An out-of-range unitEnd or negative penalty width returns InvalidInput from breakParagraph. Record and Item construction preserve the supplied data until that call validates it.
A complete plan needs a selectable terminal candidate at the unit count. Paragraph planning does not synthesize a terminal penalty or invoke break classification on the measured items.
Related rule: Apply penalties at measured unit boundariesResult
The declared result type is Break.
Effects
Failures
Result and effects
LinkSelect this field from a value of its named type without call parentheses.
Forced prevents crossing its boundary. Forbidden removes this candidate. Allowed uses the selected model's penalty cost rule.
Why
LinkThe record keeps source identity, measured geometry, and boundary policy explicit at the paragraph planning call.
Resolved contracts
LinkRelated entries
LinkApply penalties at measured unit boundaries
LinkApply penalties at measured unit boundaries
Penalty.unitEnd is the exclusive end of a measured unit span. It must be greater than zero and no greater than the paragraph unit count. The penalty's position in the Item array does not set that boundary.
Planning collects penalties and visits them in increasing unitEnd order. Equal endpoints retain input order. Duplicate endpoints remain separate candidates and are counted separately in breakOpportunityCount.
Penalty.rule determines whether a candidate is selectable and how its additional cost is interpreted. Forbidden removes that candidate. A selectable duplicate at the same endpoint remains available. A Forced entry prevents any line from crossing that boundary.
Penalty.kind describes the selected boundary independently of its rule. For example a Forced rule can carry a LatinHyphen kind. The chosen line reports the selected candidate's kind.
Penalty.width is a nonnegative Length<Pt> that contributes when that candidate ends a line. Both cost models include this width for every kind. Unselected candidates contribute no width.
PlanLine.selectedPenaltyWidth reports that selected width separately from the measured text widths. Input penalty widths are validated even for Forbidden candidates.
Penalty.flagged marks a break for KnuthPlassPolicy.flaggedDemerit and finalFlaggedDemerit. FixedPoint does not use this flag. Its consecutive soft hyphen rule depends on kind.
An out-of-range unitEnd or negative penalty width returns InvalidInput from breakParagraph. Record and Item construction preserve the supplied data until that call validates it.
A complete plan needs a selectable terminal candidate at the unit count. Paragraph planning does not synthesize a terminal penalty or invoke break classification on the measured items.
Why
A boundary candidate separates admissibility, category, visible width, and cost history. The same selected width has one meaning in either cost model. Keeping duplicate candidates distinct permits explicit alternatives without changing source unit indices.
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
v5.21.3· 20 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 27 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 69 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 1 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 12 - compiler/crates/topaz_resolve/src/std/typeset/knuth_plass.tpz at
v5.21.3· 1 -
topaz.stdlib.contract.typeset-penaltiesatworking-tree
Include a selected nonsoft penalty width with fixed costs
Linkimport std.typeset as tsimport std.iolet items: Array<ts.Item> = [ts.Item.BoxItem(ts.Box { unitIndex: 0, text: "a", width: 4pt, trackingAfter: 0pt }),ts.Item.PenaltyItem(ts.Penalty { unitEnd: 1, width: 1pt, rule: ts.BreakRule.Forced(), kind: ts.BreakKind.LatinHyphen(), flagged: false })]let input = ts.Paragraph {grid: ts.DistanceGrid.MilliPoint(),items: items,geometry: ts.LineGeometry { bodyTarget: 5pt, firstTarget: 5pt, dropCapSpan: 0, dropCapInset: 0pt },justification: ts.JustificationPolicy {mode: ts.JustificationMode.Unjustified(), minGapCount: 0,minLineWidthRatioM: 0, minFinalLineWidthRatioM: None(),maxAdjustment: 0pt, maxGapAdjustment: 0pt, maxGapRatioR: 0,latinSpacing: None(), cjkStretchRatio: 0.0},costModel: ts.CostModel.FixedPoint(),knuthPlass: ts.KnuthPlassPolicy { toleranceR: 100000000, linePenalty: 10, fitnessDemerit: 0, flaggedDemerit: 0, finalFlaggedDemerit: 0 }}match (ts.breakParagraph(input)) {case Ok(result) => {let line = result.optimized.lines[0]io.writeLine("{line.selectedPenaltyWidth == 1pt}:{line.costTextWidth == 4pt}:{line.cost}")}case Err(_) => io.writeLine("unexpected error")}
true:true:350000000
Expected result
Expected result
Execution completes. Exit code 0.
true:true:350000000
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
v5.21.3· 20 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 27 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 69 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 1 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 12 - compiler/crates/topaz_resolve/src/std/typeset/knuth_plass.tpz at
v5.21.3· 1 -
topaz.stdlib.contract.typeset-penaltiesatworking-tree
Include a selected nonsoft penalty width with knuth costs
Linkimport std.typeset as tsimport std.iolet items: Array<ts.Item> = [ts.Item.BoxItem(ts.Box { unitIndex: 0, text: "a", width: 4pt, trackingAfter: 0pt }),ts.Item.PenaltyItem(ts.Penalty { unitEnd: 1, width: 1pt, rule: ts.BreakRule.Forced(), kind: ts.BreakKind.LatinHyphen(), flagged: false })]let input = ts.Paragraph {grid: ts.DistanceGrid.MilliPoint(),items: items,geometry: ts.LineGeometry { bodyTarget: 5pt, firstTarget: 5pt, dropCapSpan: 0, dropCapInset: 0pt },justification: ts.JustificationPolicy {mode: ts.JustificationMode.Unjustified(), minGapCount: 0,minLineWidthRatioM: 0, minFinalLineWidthRatioM: None(),maxAdjustment: 0pt, maxGapAdjustment: 0pt, maxGapRatioR: 0,latinSpacing: None(), cjkStretchRatio: 0.0},costModel: ts.CostModel.KnuthPlass(),knuthPlass: ts.KnuthPlassPolicy { toleranceR: 100000000, linePenalty: 10, fitnessDemerit: 0, flaggedDemerit: 0, finalFlaggedDemerit: 0 }}match (ts.breakParagraph(input)) {case Ok(result) => {let line = result.optimized.lines[0]io.writeLine("{line.selectedPenaltyWidth == 1pt}:{line.costTextWidth == 4pt}:{line.cost}")}case Err(_) => io.writeLine("unexpected error")}
true:true:100
Expected result
Expected result
Execution completes. Exit code 0.
true:true:100
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
v5.21.3· 20 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 27 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 69 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 1 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 12 - compiler/crates/topaz_resolve/src/std/typeset/knuth_plass.tpz at
v5.21.3· 1 -
topaz.stdlib.contract.typeset-penaltiesatworking-tree
Reject boundaries outside the measured units
Linkimport std.typeset as tsimport std.iofunction report(items: Array<ts.Item>) -> () {let input = ts.Paragraph {grid: ts.DistanceGrid.MilliPoint(),items: items,geometry: ts.LineGeometry { bodyTarget: 10pt, firstTarget: 10pt, dropCapSpan: 0, dropCapInset: 0pt },justification: ts.JustificationPolicy {mode: ts.JustificationMode.Unjustified(), minGapCount: 0,minLineWidthRatioM: 0, minFinalLineWidthRatioM: None(),maxAdjustment: 0pt, maxGapAdjustment: 0pt, maxGapRatioR: 0,latinSpacing: None(), cjkStretchRatio: 0.0},costModel: ts.CostModel.FixedPoint(),knuthPlass: ts.KnuthPlassPolicy { toleranceR: 100000000, linePenalty: 10, fitnessDemerit: 0, flaggedDemerit: 0, finalFlaggedDemerit: 0 }}match (ts.breakParagraph(input)) {case Err(InvalidInput(_)) => io.writeLine("InvalidInput")case _ => io.writeLine("unexpected result")}}report([ts.Item.BoxItem(ts.Box { unitIndex: 0, text: "a", width: 1pt, trackingAfter: 0pt }), ts.Item.PenaltyItem(ts.Penalty { unitEnd: 0, width: 0pt, rule: ts.BreakRule.Forced(), kind: ts.BreakKind.ForcedEnd(), flagged: false })])report([ts.Item.BoxItem(ts.Box { unitIndex: 0, text: "a", width: 1pt, trackingAfter: 0pt }), ts.Item.PenaltyItem(ts.Penalty { unitEnd: 2, width: 0pt, rule: ts.BreakRule.Forced(), kind: ts.BreakKind.ForcedEnd(), flagged: false })])
InvalidInput InvalidInput
Expected result
Expected result
Execution completes. Exit code 0.
InvalidInputInvalidInput
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
v5.21.3· 20 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 27 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 69 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 1 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 12 - compiler/crates/topaz_resolve/src/std/typeset/knuth_plass.tpz at
v5.21.3· 1 -
topaz.stdlib.contract.typeset-penaltiesatworking-tree
Reject a negative boundary width
Linkimport std.typeset as tsimport std.iolet items: Array<ts.Item> = [ts.Item.BoxItem(ts.Box { unitIndex: 0, text: "a", width: 1pt, trackingAfter: 0pt }),ts.Item.PenaltyItem(ts.Penalty { unitEnd: 1, width: -1pt, rule: ts.BreakRule.Forced(), kind: ts.BreakKind.ForcedEnd(), flagged: false })]let input = ts.Paragraph {grid: ts.DistanceGrid.MilliPoint(),items: items,geometry: ts.LineGeometry { bodyTarget: 10pt, firstTarget: 10pt, dropCapSpan: 0, dropCapInset: 0pt },justification: ts.JustificationPolicy {mode: ts.JustificationMode.Unjustified(), minGapCount: 0,minLineWidthRatioM: 0, minFinalLineWidthRatioM: None(),maxAdjustment: 0pt, maxGapAdjustment: 0pt, maxGapRatioR: 0,latinSpacing: None(), cjkStretchRatio: 0.0},costModel: ts.CostModel.FixedPoint(),knuthPlass: ts.KnuthPlassPolicy { toleranceR: 100000000, linePenalty: 10, fitnessDemerit: 0, flaggedDemerit: 0, finalFlaggedDemerit: 0 }}match (ts.breakParagraph(input)) {case Err(InvalidInput(_)) => io.writeLine("InvalidInput")case _ => io.writeLine("unexpected result")}
InvalidInput
Expected result
Expected result
Execution completes. Exit code 0.
InvalidInput
Source evidence
- compiler/crates/topaz_resolve/src/std/typeset/model.tpz at
v5.21.3· 20 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 27 - compiler/crates/topaz_resolve/src/std/typeset/measure.tpz at
v5.21.3· 69 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 1 - compiler/crates/topaz_resolve/src/std/typeset/line.tpz at
v5.21.3· 12 - compiler/crates/topaz_resolve/src/std/typeset/knuth_plass.tpz at
v5.21.3· 1 -
topaz.stdlib.contract.typeset-penaltiesatworking-tree