Repository navigation
Text API #224
Description
Activity
- addedengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.a: text inputEntering text in a text field or keyboard related problemsEntering text in a text field or keyboard related problemsc: new featureNothing broken; request for a new capabilityNothing broken; request for a new capability
on Nov 9, 2015 Comment by j9brown
Sunday Oct 25, 2015 at 01:09 GMT
Great list of properties! A few more details that will be necessary for text input and editing:
- grapheme cluster boundaries
- valid cursor X positions on a line (insertion point)
- mapping between logical and visual runs
One subtlety: do not use character index directly to represent the insertion point. Or at least, be sure to distinguish end-of-line and beginning-of-line positions when line wrapping occurs at a particular character index.
For example, suppose the insertion point is modeled as a character index in a text buffer containing: "The quick brown fox\njumped over the lazy dog."
We can imagine a text API where the cursor's positions is based only on character index. If the insertion point is at index 0 then the cursor is placed right at the start of the buffer, if it is at 3, it is placed just after "The", if it is at strlen(text) then it is placed right at the end of the buffer. All seems well until line wrapping occurs.
When line wrapping is explicit, as I indicated with an embedded newline, then there can be distinguishable character indices corresponding to the end of one line and the beginning of the next. Placing the insertion point at the character index for "\n" can position the cursor at the end of one line, placing it just after the "\n" can position it at the beginning of the next line. So each valid placement of the cursor corresponds to a distinguishable character index.
However when line wrapping is implicit due to text reflow, the naive correspondence of character index and insertion point breaks down. Suppose the text wrapped after "over " due to lack of space on the line. What character index would you use to position the cursor at the end of the line including "over "? How about the beginning the of the line that follows? Tricky.
The situation becomes more complex when we consider cursor positioning within grapheme clusters.
This can have a significant impact on how text selection APIs are designed.
Comment by Hixie
Sunday Oct 25, 2015 at 01:50 GMT
The insertion point logic is a layer above this (entirely in Dart, as opposed to this issue, which is the C++-implemented API to the Dart layer). Given that, I think that the first two you list would just be layered on top of "advance width from the start of the line to the end of the glyph to which the character at a particular index corresponds". No?
Can you elaborate on the third?
- Replaced inlines: the ability to give a placeholder position in the text with a width, height, baseline alignment offset, and a reference to an SkPicture to embed at whatever position the placeholder ends up taking.
- modified the milestones: This milestone has been deleted, This milestone has been deleted
on Sep 16, 2016 We would like to be able to animate some text while varying opacity/color. This is very expensive with repeated calls to Paragraph.layout(), so +1 to:
"a way to change the Paint efficiently (e.g. change colour without a new layout)."Is there timeframe for this feature?
Reacted by suragch, Greg Lowe and sagarkardani24 remaining items
Advance Width for each character still not implemented?
SelectableText-Text-TextSpanwidgets: when using a Japanese String it can't split the input Japanese string into words. problem in wrapping it splits the WORD by character's not as a word which led to a half word above and the rest bellow.@walidbou6 Is a dictionary necessary in order to split Japanese text into words? Maybe file a separate issue.
@justinmc for Japanese it has no spaces to split words as in English or other languages, but even when I add spaces to split it into list of words, it's still can't get the Text wrapped, I just used an alternative solution by creating my own wrapper :
String wrapper(text, width) { String clean = text.replaceAll(RegExp(r"[\t\n\r\s ]"), " "); clean = clean.replaceAll(RegExp(r'\s+'), ' '); List<String> chunks = clean.split(' '); List<String> lines = []; while (chunks.isNotEmpty) { List<String> curLine = []; int curLen = 0; if (chunks[0].trim() == '' && lines.isNotEmpty) { chunks.removeAt(0); } while (chunks.isNotEmpty) { int l = chunks[0].length + 1; if (curLen + l <= width) { curLine.add(chunks[0]); chunks.removeAt(0); curLen += l; } else { break; } } if (chunks.isNotEmpty && (chunks[0].length + 1) > width) { if (curLine.isEmpty) { curLine.add(chunks[0]); chunks.removeAt(0); } curLen = sumLen(curLine); } if (curLine.isNotEmpty) { if (chunks.length == 1 || curLen <= width) { lines.add(curLine.join(' ')); } } } return lines.join('\n'); } int sumLen(list) { int res = 0; for (String x in list) { res += x.length; } return res; }
this script my need some modifications because it's not flexible if you change the font size or font family you should change as will the wrapper
width.I'm going to close this. If there are specific typographical features we still need to add, we should track them as individual issues.
Reacted by Justin McCandlessThis thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Mar 7, 2023
Text consists of a series of glyphs from one or more fonts. Each series of glyphs that uses a specific font is placed in a box. The boxes are all aligned along a common baseline, which is either the alphabetic baseline (e.g. for English text), the ideographic baseline (e.g. for CJK characters), the hanging baseline (e.g. for Thai), or the mathematical baseline. The boxes have several heights: the em height (the font size), the line height (the font size times the line height factor for that box), the font box height, and the bounding box height (see note 2). The line height is positioned such that it has the same difference from the em height above and below the baseline. The boxes are line-wrapped and placed vertically below each other. The text origin is the point at the start (i.e. before the first character) of the first line, on the chosen baseline.
We should expose the following inputs for the text painting and layout algorithm:
The input consists of a tree of boxes annotated with the data marked with asterisks * in the list above. The baselines of the outermost box set the metrics to use for baseline alignment. On each line, the boxes are positioned vertically according to the settings, and then those that contribute their line height are examined. The distance from one line to the next is the distance from the baseline of the first, to the bottom of the bottommost line height box on that line, plus the distance from the top of the topmost line height box on the next line, to the baseline of that second line.
We should expose the following metrics for text:
Note 1: Because of bidi, the "end" of a character could be on the left or the right. For example, for "bب", if both characters are 10 units wide, and the configured text direction is ltr, the advance widths would be 10 and 10, even though the advance width of the whole string would be 20. The direction at the end of each character would be "ltr" and "rtl" respectively. If the string was wrapped in between the two characters, the line-specific advance width for the second line's first character would be 0, and both lines would have an advance width of 10 (the total advance width would still be 20).
Note 2: Each font has a font bounding box, which is the space the font would need to render the character that reaches the highest and the character that reaches the lowest. A specific span of text has a bounding box that is usually smaller than this (because most text doesn't include the extreme characters). If the text is a single period, it's much smaller than if it's a lowercase "o", which would itself be much smaller than if the text was an uppercase "F". Some fonts have particular characters that on their own will wildly increase the bounding box dimensions (e.g. Zapfino's lowercase "f").
Note 3: The fonts used depends on the characters used. If the text only consists of the letter "a", then it'll all be from the same font. If the text is "a林" then it might come from two fonts, one with latin characters and one with ideographic characters. However, the font box height given a particular set of fonts is independent of the actual characters. That is, if "a" and "b" end up using the same font, then they have the same font box dimensions (but probably different actual bounding box dimensions).
Note 4: We don't need to support bidi embeddings. Those can be done using explicit bidi formatting characters. We don't need to support the equivalent of "unicode-bidi: plaintext", that can be implemented at the Dart level.