diff --git a/lib/core/models/styles/text_editor_style.dart b/lib/core/models/styles/text_editor_style.dart index 5a0ebe7e..1554c604 100644 --- a/lib/core/models/styles/text_editor_style.dart +++ b/lib/core/models/styles/text_editor_style.dart @@ -1,4 +1,6 @@ // Flutter imports: +import 'dart:ui' as ui; + import 'package:flutter/material.dart'; import '../../constants/editor_style_constants.dart'; @@ -53,6 +55,7 @@ class TextEditorStyle { /// style properties. const TextEditorStyle({ this.textHeight = 0.0, + this.leadingDistribution = ui.TextLeadingDistribution.proportional, this.fontSizeBottomSheetTitle, this.textFieldMargin = const EdgeInsets.only( bottom: kBottomNavigationBarHeight, @@ -126,6 +129,19 @@ class TextEditorStyle { /// on various platforms. Set to null to use the default line height. final double? textHeight; + /// Controls how extra leading from the [TextStyle.height] multiplier is + /// distributed above and below the text glyph. + /// + /// [TextLeadingDistribution.proportional] distributes leading proportional + /// to the font's ascent / descent ratio (~75% above, ~25% below for most + /// Latin fonts). This is the default and matches Flutter's standard + /// rendering. + /// + /// [TextLeadingDistribution.even] splits the extra leading 50 / 50, which + /// visually centres glyphs inside their rounded background rects when + /// [TextStyle.height] is greater than 1.0. + final ui.TextLeadingDistribution leadingDistribution; + /// Creates a copy of this `TextEditorStyle` object with the given fields /// replaced with new values. /// @@ -134,6 +150,7 @@ class TextEditorStyle { /// others unchanged. TextEditorStyle copyWith({ double? textHeight, + ui.TextLeadingDistribution? leadingDistribution, Color? appBarBackground, Color? appBarColor, Color? bottomBarBackground, @@ -152,6 +169,7 @@ class TextEditorStyle { }) { return TextEditorStyle( textHeight: textHeight ?? this.textHeight, + leadingDistribution: leadingDistribution ?? this.leadingDistribution, fontScaleBottomSheetBackground: fontScaleBottomSheetBackground ?? this.fontScaleBottomSheetBackground, appBarBackground: appBarBackground ?? this.appBarBackground, diff --git a/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text.dart b/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text.dart index 4dcc3951..64aacf9b 100644 --- a/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text.dart +++ b/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text.dart @@ -26,6 +26,7 @@ class RoundedBackgroundText extends StatelessWidget { required this.maxTextWidth, this.cursorWidth = 0, this.enableHitBoxCorrection = false, + this.leadingDistribution = TextLeadingDistribution.proportional, }) : text = TextSpan(text: text, style: style); /// Creates a [RoundedBackgroundText] widget with rich text using @@ -42,6 +43,7 @@ class RoundedBackgroundText extends StatelessWidget { required this.maxTextWidth, this.cursorWidth = 0, this.enableHitBoxCorrection = false, + this.leadingDistribution = TextLeadingDistribution.proportional, }); /// A flag to enable or disable hitBox correction for the text. @@ -64,6 +66,13 @@ class RoundedBackgroundText extends StatelessWidget { /// The width of the text cursor when displayed. final double cursorWidth; + /// Controls how extra leading is distributed above and below the text. + /// + /// Defaults to [TextLeadingDistribution.proportional]. + /// Set to [TextLeadingDistribution.even] to visually centre glyphs inside + /// their rounded background rects when [TextStyle.height] > 1.0. + final TextLeadingDistribution leadingDistribution; + /// Callback function triggered with the result of a hit test. final Function(bool hasHit)? onHitTestResult; @@ -76,9 +85,7 @@ class RoundedBackgroundText extends StatelessWidget { final painter = TextPainter( text: TextSpan( children: [text], - style: const TextStyle( - leadingDistribution: TextLeadingDistribution.proportional, - ).merge(style), + style: TextStyle(leadingDistribution: leadingDistribution).merge(style), ), textDirection: Directionality.maybeOf(context) ?? TextDirection.ltr, maxLines: defaultTextStyle.maxLines, @@ -140,6 +147,13 @@ class RoundedBackgroundText extends StatelessWidget { value: onHitTestResult != null, ifTrue: 'callback set', ), + ) + ..add( + EnumProperty( + 'leadingDistribution', + leadingDistribution, + defaultValue: TextLeadingDistribution.proportional, + ), ); } } diff --git a/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text_field.dart b/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text_field.dart index c0a855b0..1dff4112 100644 --- a/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text_field.dart +++ b/lib/features/text_editor/widgets/rounded_background_text/rounded_background_text_field.dart @@ -140,7 +140,7 @@ class _RoundedBackgroundTextFieldState Widget _buildBackgroundText() { final style = widget.style.copyWith( color: Colors.transparent, - leadingDistribution: TextLeadingDistribution.proportional, + leadingDistribution: widget.configs.style.leadingDistribution, ); return Positioned( @@ -183,7 +183,7 @@ class _RoundedBackgroundTextFieldState scrollPadding: EdgeInsets.zero, style: widget.style.copyWith( fontSize: fontSize, - leadingDistribution: TextLeadingDistribution.proportional, + leadingDistribution: widget.configs.style.leadingDistribution, height: widget.configs.style.textHeight, ), decoration: InputDecoration.collapsed( diff --git a/lib/shared/widgets/layer/widgets/layer_widget_text_item.dart b/lib/shared/widgets/layer/widgets/layer_widget_text_item.dart index 0db7207f..2877174a 100644 --- a/lib/shared/widgets/layer/widgets/layer_widget_text_item.dart +++ b/lib/shared/widgets/layer/widgets/layer_widget_text_item.dart @@ -77,6 +77,7 @@ class LayerWidgetTextItem extends StatelessWidget { backgroundColor: layer.background, textAlign: layer.align, style: finalStyle, + leadingDistribution: textEditorConfigs.style.leadingDistribution, ); }