Files
clide/test/terminal/painter_bold_metrics_test.dart
T
jpmschweitzerandClaude a67a768592 restore semantic bold rendering in terminal panes (T-73)
Bold attributes from terminal escapes now render in a real bold
weight instead of being silently flattened.

- pubspec.yaml: register JetBrainsMono Bold + BoldItalic at
  weight 700 under family JetBrainsMono. Files already shipped on
  disk; only the registration was missing.
- assets/licenses.yaml: bump JetBrainsMono weights_bundled to
  [Regular, Italic, Bold, BoldItalic] per D-42 (the entry must
  match what is actually wired into the family).
- lib/src/terminal/src/ui/painter.dart: revert the `bold: false`
  override and drop the workaround comment. Bold now flows from
  CellFlags.bold to TextStyle.fontWeight.
- test/terminal/painter_bold_metrics_test.dart: load Regular and
  Bold via FontLoader and assert paragraph maxIntrinsicWidth is
  identical (cell-grid drift = 0). JetBrainsMono Bold's monospace
  by spec; this test is the canary for the day someone swaps the
  font.
- test/goldens/goldens/{ci,linux}/clide_button.png: regenerate.
  ClideButton's label renders slightly heavier on the bold variant
  (expected — 0.28% pixel diff before regen).

Earlier perception of over-bolding in the Claude pane was
synthetic-bold smearing (Flutter overpaints when no Bold.ttf is
registered for the family), not legitimate bold rendering. Visual
A/B confirms a real Bold face renders crisp emphasis without the
smear, so no per-pane renderer config is needed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-05-06 22:29:23 +02:00

56 lines
1.9 KiB
Dart

/// Verifies that the bundled JetBrainsMono Bold face has identical
/// advance widths to Regular at our render size — required for the
/// terminal cell grid to stay stable when bold attributes flip on.
///
/// If this fails, the workaround in painter.dart was deactivated
/// against a font that drifts; pick one of the alternatives in T-73
/// (variable JetBrainsMono / Berkeley Mono / IBM Plex Mono).
library;
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
const _family = 'JetBrainsMonoTest';
const _fontSize = 14.0;
const _sample = 'mmmmmmmmmm';
void main() {
setUpAll(() async {
final regular = await File('assets/fonts/jetbrains_mono/JetBrainsMono-Regular.ttf').readAsBytes();
final bold = await File('assets/fonts/jetbrains_mono/JetBrainsMono-Bold.ttf').readAsBytes();
final loader = FontLoader(_family)
..addFont(Future.value(ByteData.sublistView(regular)))
..addFont(Future.value(ByteData.sublistView(bold)));
await loader.load();
});
test('JetBrainsMono Bold advance width matches Regular (cell drift = 0)', () {
final regularWidth = _measure(FontWeight.normal);
final boldWidth = _measure(FontWeight.bold);
expect(boldWidth, regularWidth,
reason: 'Bold advance width must equal Regular at $_fontSize px '
'or the terminal cell grid drifts when bold flips on.');
});
}
double _measure(FontWeight weight) {
final builder = ui.ParagraphBuilder(ui.ParagraphStyle(
fontFamily: _family,
fontSize: _fontSize,
))
..pushStyle(ui.TextStyle(
fontFamily: _family,
fontWeight: weight,
fontSize: _fontSize,
))
..addText(_sample);
final paragraph = builder.build()..layout(const ui.ParagraphConstraints(width: double.infinity));
final width = paragraph.maxIntrinsicWidth;
paragraph.dispose();
return width;
}