Skip to content

Commit 1efc4b8

Browse files
committed
feat(text-editor): add configurable leadingDistribution to TextEditorStyle
Add a new leadingDistribution property to TextEditorStyle that controls how extra leading is distributed above and below text glyphs. Default: TextLeadingDistribution.proportional (preserves existing behavior). When set to TextLeadingDistribution.even, glyphs are vertically centered within their line height bounds, fixing visual misalignment of text inside rounded background rects at line heights > 1.0. Changes: - TextEditorStyle: new leadingDistribution property with copyWith support - RoundedBackgroundTextField: both builders read from config instead of hardcoding proportional - RoundedBackgroundText: new leadingDistribution parameter on both constructors, wired to parent TextSpan and debugFillProperties - LayerWidgetTextItem: passes config value to RoundedBackgroundText so saved layers match the editing style
1 parent bc2165a commit 1efc4b8

4 files changed

Lines changed: 39 additions & 4 deletions

File tree

lib/core/models/styles/text_editor_style.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// Flutter imports:
2+
import 'dart:ui' as ui;
3+
24
import 'package:flutter/material.dart';
35

46
import '../../constants/editor_style_constants.dart';
@@ -53,6 +55,7 @@ class TextEditorStyle {
5355
/// style properties.
5456
const TextEditorStyle({
5557
this.textHeight = 0.0,
58+
this.leadingDistribution = ui.TextLeadingDistribution.proportional,
5659
this.fontSizeBottomSheetTitle,
5760
this.textFieldMargin = const EdgeInsets.only(
5861
bottom: kBottomNavigationBarHeight,
@@ -126,6 +129,19 @@ class TextEditorStyle {
126129
/// on various platforms. Set to null to use the default line height.
127130
final double? textHeight;
128131

132+
/// Controls how extra leading from the [TextStyle.height] multiplier is
133+
/// distributed above and below the text glyph.
134+
///
135+
/// [TextLeadingDistribution.proportional] distributes leading proportional
136+
/// to the font's ascent / descent ratio (~75% above, ~25% below for most
137+
/// Latin fonts). This is the default and matches Flutter's standard
138+
/// rendering.
139+
///
140+
/// [TextLeadingDistribution.even] splits the extra leading 50 / 50, which
141+
/// visually centres glyphs inside their rounded background rects when
142+
/// [TextStyle.height] is greater than 1.0.
143+
final ui.TextLeadingDistribution leadingDistribution;
144+
129145
/// Creates a copy of this `TextEditorStyle` object with the given fields
130146
/// replaced with new values.
131147
///
@@ -134,6 +150,7 @@ class TextEditorStyle {
134150
/// others unchanged.
135151
TextEditorStyle copyWith({
136152
double? textHeight,
153+
ui.TextLeadingDistribution? leadingDistribution,
137154
Color? appBarBackground,
138155
Color? appBarColor,
139156
Color? bottomBarBackground,
@@ -152,6 +169,7 @@ class TextEditorStyle {
152169
}) {
153170
return TextEditorStyle(
154171
textHeight: textHeight ?? this.textHeight,
172+
leadingDistribution: leadingDistribution ?? this.leadingDistribution,
155173
fontScaleBottomSheetBackground:
156174
fontScaleBottomSheetBackground ?? this.fontScaleBottomSheetBackground,
157175
appBarBackground: appBarBackground ?? this.appBarBackground,

lib/features/text_editor/widgets/rounded_background_text/rounded_background_text.dart

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class RoundedBackgroundText extends StatelessWidget {
2626
required this.maxTextWidth,
2727
this.cursorWidth = 0,
2828
this.enableHitBoxCorrection = false,
29+
this.leadingDistribution = TextLeadingDistribution.proportional,
2930
}) : text = TextSpan(text: text, style: style);
3031

3132
/// Creates a [RoundedBackgroundText] widget with rich text using
@@ -42,6 +43,7 @@ class RoundedBackgroundText extends StatelessWidget {
4243
required this.maxTextWidth,
4344
this.cursorWidth = 0,
4445
this.enableHitBoxCorrection = false,
46+
this.leadingDistribution = TextLeadingDistribution.proportional,
4547
});
4648

4749
/// A flag to enable or disable hitBox correction for the text.
@@ -64,6 +66,13 @@ class RoundedBackgroundText extends StatelessWidget {
6466
/// The width of the text cursor when displayed.
6567
final double cursorWidth;
6668

69+
/// Controls how extra leading is distributed above and below the text.
70+
///
71+
/// Defaults to [TextLeadingDistribution.proportional].
72+
/// Set to [TextLeadingDistribution.even] to visually centre glyphs inside
73+
/// their rounded background rects when [TextStyle.height] > 1.0.
74+
final TextLeadingDistribution leadingDistribution;
75+
6776
/// Callback function triggered with the result of a hit test.
6877
final Function(bool hasHit)? onHitTestResult;
6978

@@ -76,8 +85,8 @@ class RoundedBackgroundText extends StatelessWidget {
7685
final painter = TextPainter(
7786
text: TextSpan(
7887
children: [text],
79-
style: const TextStyle(
80-
leadingDistribution: TextLeadingDistribution.proportional,
88+
style: TextStyle(
89+
leadingDistribution: leadingDistribution,
8190
).merge(style),
8291
),
8392
textDirection: Directionality.maybeOf(context) ?? TextDirection.ltr,
@@ -140,6 +149,13 @@ class RoundedBackgroundText extends StatelessWidget {
140149
value: onHitTestResult != null,
141150
ifTrue: 'callback set',
142151
),
152+
)
153+
..add(
154+
EnumProperty<TextLeadingDistribution>(
155+
'leadingDistribution',
156+
leadingDistribution,
157+
defaultValue: TextLeadingDistribution.proportional,
158+
),
143159
);
144160
}
145161
}

lib/features/text_editor/widgets/rounded_background_text/rounded_background_text_field.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ class _RoundedBackgroundTextFieldState
140140
Widget _buildBackgroundText() {
141141
final style = widget.style.copyWith(
142142
color: Colors.transparent,
143-
leadingDistribution: TextLeadingDistribution.proportional,
143+
leadingDistribution: widget.configs.style.leadingDistribution,
144144
);
145145

146146
return Positioned(
@@ -183,7 +183,7 @@ class _RoundedBackgroundTextFieldState
183183
scrollPadding: EdgeInsets.zero,
184184
style: widget.style.copyWith(
185185
fontSize: fontSize,
186-
leadingDistribution: TextLeadingDistribution.proportional,
186+
leadingDistribution: widget.configs.style.leadingDistribution,
187187
height: widget.configs.style.textHeight,
188188
),
189189
decoration: InputDecoration.collapsed(

lib/shared/widgets/layer/widgets/layer_widget_text_item.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class LayerWidgetTextItem extends StatelessWidget {
7777
backgroundColor: layer.background,
7878
textAlign: layer.align,
7979
style: finalStyle,
80+
leadingDistribution: textEditorConfigs.style.leadingDistribution,
8081
);
8182
}
8283

0 commit comments

Comments
 (0)