Subscript and Superscript

pull/1909/head
AtlasAutocode 11 months ago
parent 9455dd49bf
commit 00783adf91
  1. 8
      lib/src/models/config/quill_controller_configurations.dart
  2. 1
      lib/src/widgets/editor/editor.dart
  3. 60
      lib/src/widgets/quill/text_line.dart

@ -1,8 +1,14 @@
class QuillControllerConfigurations { class QuillControllerConfigurations {
const QuillControllerConfigurations({this.onClipboardPaste}); const QuillControllerConfigurations(
{this.onClipboardPaste, this.requireScriptFontFeatures = false});
/// Callback when the user pastes and data has not already been processed /// Callback when the user pastes and data has not already been processed
/// ///
/// Return true if the paste operation was handled /// Return true if the paste operation was handled
final Future<bool> Function()? onClipboardPaste; final Future<bool> Function()? onClipboardPaste;
/// Render subscript and superscript text using Open Type FontFeatures
///
/// Default is false to use built-in script rendering that is independent of font capabilities
final bool requireScriptFontFeatures;
} }

@ -173,6 +173,7 @@ class QuillEditorState extends State<QuillEditor>
void initState() { void initState() {
super.initState(); super.initState();
widget.configurations.controller.editorFocusNode ??= widget.focusNode; widget.configurations.controller.editorFocusNode ??= widget.focusNode;
widget.configurations.controller.editorFocusNode?.requestFocus();
_editorKey = configurations.editorKey ?? GlobalKey<EditorState>(); _editorKey = configurations.editorKey ?? GlobalKey<EditorState>();
_selectionGestureDetectorBuilder = _selectionGestureDetectorBuilder =
_QuillEditorSelectionGestureDetectorBuilder( _QuillEditorSelectionGestureDetectorBuilder(

@ -322,19 +322,71 @@ class _TextLineState extends State<TextLine> {
return textStyle; return textStyle;
} }
TextSpan _getTextSpanFromNode( /// Processes subscript and superscript attributed text.
///
/// Reduces text fontSize and shifts down or up. Increases fontWeight to maintain balance with normal text.
/// Outputs characters individually to allow correct caret positioning and text selection.
InlineSpan _scriptSpan(String text, bool superScript, TextStyle style,
DefaultStyles defaultStyles) {
assert(text.isNotEmpty);
//
final lineStyle = style.fontSize == null || style.fontWeight == null
? _getLineStyle(defaultStyles)
: null;
final fontWeight = FontWeight.lerp(
style.fontWeight ?? lineStyle?.fontWeight ?? FontWeight.normal,
FontWeight.w900,
0.25);
final fontSize = style.fontSize ?? lineStyle?.fontSize ?? 16;
final y = (superScript ? -0.4 : 0.14) * fontSize;
final charStyle = style.copyWith(
fontFeatures: <FontFeature>[],
fontWeight: fontWeight,
fontSize: fontSize * 0.7);
//
final offset = Offset(0, y);
final children = <WidgetSpan>[];
for (final c in text.characters) {
children.add(WidgetSpan(
child: Transform.translate(
offset: offset,
child: Text(
c,
style: charStyle,
))));
}
//
if (children.length > 1) {
return TextSpan(children: children);
}
return children[0];
}
InlineSpan _getTextSpanFromNode(
DefaultStyles defaultStyles, Node node, Style lineStyle) { DefaultStyles defaultStyles, Node node, Style lineStyle) {
final textNode = node as leaf.QuillText; final textNode = node as leaf.QuillText;
final nodeStyle = textNode.style; final nodeStyle = textNode.style;
final isLink = nodeStyle.containsKey(Attribute.link.key) && final isLink = nodeStyle.containsKey(Attribute.link.key) &&
nodeStyle.attributes[Attribute.link.key]!.value != null; nodeStyle.attributes[Attribute.link.key]!.value != null;
final recognizer = _getRecognizer(node, isLink); final style = _getInlineTextStyle(
textNode, defaultStyles, nodeStyle, lineStyle, isLink);
if (widget.controller.configurations.requireScriptFontFeatures == false &&
textNode.value.isNotEmpty) {
if (nodeStyle.containsKey(Attribute.script.key)) {
final attr = nodeStyle.attributes[Attribute.script.key];
if (attr == Attribute.superscript || attr == Attribute.subscript) {
return _scriptSpan(textNode.value, attr == Attribute.superscript,
style, defaultStyles);
}
}
}
final recognizer = _getRecognizer(node, isLink);
return TextSpan( return TextSpan(
text: textNode.value, text: textNode.value,
style: _getInlineTextStyle( style: style,
textNode, defaultStyles, nodeStyle, lineStyle, isLink),
recognizer: recognizer, recognizer: recognizer,
mouseCursor: (recognizer != null) ? SystemMouseCursors.click : null, mouseCursor: (recognizer != null) ? SystemMouseCursors.click : null,
); );

Loading…
Cancel
Save