8000 Enable dart:ui APIs for text measurement in secondary isolates · Issue #30604 · flutter/flutter · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Enable dart:ui APIs for text measurement in secondary isolates #30604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
windrunner414 opened this issue Apr 6, 2019 · 28 comments
Open

Enable dart:ui APIs for text measurement in secondary isolates #30604

windrunner414 opened this issue Apr 6, 2019 · 28 comments
Labels
a: typography Text rendering, possibly libtxt c: new feature Nothing broken; request for a new capability engine flutter/engine repository. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list team-engine Owned by Engine team triaged-engine Triaged by Engine team

Comments

@windrunner414
Copy link

if use TextPainter.layout in isolate will get a compiler error native function not found
I need layout many words and it takes a long time (100ms+), it will block UI thread
What should I do?

@dnfield dnfield added engine flutter/engine repository. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. c: new feature Nothing broken; request for a new capability labels Apr 6, 2019
@dnfield
Copy link
Contributor
dnfield commented Apr 6, 2019

Can you provide the code that causes this error?

@dnfield dnfield added this to the Goals milestone Apr 6, 2019
@windrunner414
Copy link
Author
windrunner414 commented Apr 6, 2019
void test(String str){
  TextPainter(textDirection: TextDirection.ltr, text: TextSpan(text: str)).layout();
}
compute(test, '1');

@jason-simmons
Copy link
Member

The Flutter engine native APIs for the UI package are only available in the primary isolate.

See https://github.com/flutter/engine/blob/master/lib/ui/dart_ui.cc#L102

@dnfield
Copy link
Contributor
dnfield commented Apr 9, 2019

I'm not sure we could even make sense of doing this async.

If layout isn't finished, we can't paint anyway.

If we block until layout is finished, we can't paint until layout is finished anyway, and we potentially introduce deadlocks.

That said, it seems like it would be nice to be able to pre-layout text - or, alternatively, let the user paint text without specifying layout, which I think should still be possible today.

@windrunner414 - what happens if you run your compute call to do your own line breaking logic, and then just instantiate single TextPainters for each line, and position/paint them yourself?

Something like:

class StringAndOffset {
  const StringAndOffset(this.string, this.offset) : assert(string != null), assert(offset != null);
  final String string;
  final Offset offset;
}

List<StringAndOffset> test(String str) {
  // Break up `str` into strings and offsets, and return them.
}

final List<StringAndOffset> stringsAndOffsets  = await compute(test, '1');
// iterate stringsAndOffsets to create TextPainters that should layout much more quickly now on the UI thread

If that works out, it may be worth encapsulating somehow into an API, but hopefully if nothing else gets you unblocked.

@windrunner414
Copy link
Author

@dnfield how to get character's size to layout?we can't use TextPainter

@windrunner414
Copy link
Author

I find it interesting that textpainter seems to cache the size of each character. Caching is ineffective if you use compute

@windrunner414
Copy link
Author
windrunner414 commented Apr 10, 2019

I layout 5000 characters, including 2500 different characters.The first time took 1500ms!After that it only takes 15ms
after layout we need to split it in many page, like this

    double textHeight = textPainter.height;
    double lineHeight = textPainter.preferredLineHeight;
    double pageHeight = size.height - padding.top - padding.bottom;
    int lineNumber = textHeight ~/ lineHeight;
    int lineNumberPerPage = pageHeight ~/ lineHeight;
    int pageNum = (lineNumber / lineNumberPerPage).ceil();
    double actualPageHeight = lineNumberPerPage * lineHeight;

    List<Picture> pages = List<Picture>(pageNum);
    for (int i = 0; i < pageNum; ++i) {
      PictureRecorder pictureRecorder = PictureRecorder();
      Canvas canvas = Canvas(pictureRecorder);
      canvas.clipPath(Path()
        ..moveTo(padding.left, padding.top)
        ..lineTo(size.width - padding.right, padding.top)
        ..lineTo(size.width - padding.right, padding.top + actualPageHeight)
        ..lineTo(padding.left, padding.top + actualPageHeight)
        ..close());
      canvas.translate(padding.left, -i * actualPageHeight + padding.top);
      textPainter.paint(canvas, Offset(0, 0));
      pages[i] = pictureRecorder.endRecording();

i don't think it's a good way and I don't know what text is on every page.
I use TextPainter + Canvas i think it's difficult to add other widget to the text or support long press selection

@lwlizhe
Copy link
lwlizhe commented Aug 29, 2019

same question,so if we need to perform an expensive computation use textPainter,how to do it?

@dnfield dnfield added the a: typography Text rendering, possibly libtxt label Aug 29, 2019
@dnfield
Copy link
Contributor
dnfield commented Aug 29, 2019

right now you would have to write your own line-breaking logic - perhaps as a plugin. We don't currently have any API for doing text layout in a separate isolate. @GaryQian might have some other idea about this too.

@javanli

This comment has been minimized.

@a-v-ebrahimi

This comment has been minimized.

@windrunner414

This comment has been minimized.

@GaryQian GaryQian changed the title Can't use TextPainter in isolate Enable async text layout and painting. Apr 23, 2020
@kokocooler2020

This comment has been minimized.

@ahsanalidev

This comment has been minimized.

@kf6gpe kf6gpe added the P2 Important issues not at the top of the work list label May 29, 2020
@leetomlee123

This comment has been minimized.

@miphik

This comment has been minimized.

@dnfield

This comment has been minimized.

@danielgomezrico
Copy link
Contributor

This is very useful for building map markers too, I mean, not only for building text but for map markers.

In my app we have a lot of markers and building them every time is causing some UI freezes, but we use PictureRecorder to build them and they result in:

Exception: UI actions are only available on root isolate.
	#0      PictureRecorder._constructor (dart:ui/painting.dart:4458:59)
	#1      new PictureRecorder (dart:ui/painting.dart:4457:23)
	#2      IconGenerator._drawCircle (package:client/src/common/utils/map/icon_generator.dart:87:32)
	#3      IconGenerator.buildCircle (package:client/src/common/utils/map/icon_generator.dart:51:26)
	#4      MarkerGenerator._buildDots.<anonymous closure> (package:client/src/common/utils/map/marker_generator.dart:62:37)
	#5      MappedListIterable.elementAt (dart:_internal/iterable.dart:417:31)
	#6      ListIterator.moveNext (dart:_internal/iterable.dart:343:26)
	#7      Future.wait (dart:async/future.dart:406:26)
	#8      MarkerGenerator._buildDots (package:client/src/common/utils/map/marker_generator.dart:68:19)
	#9      MarkerGenerator.build (package:client/src/common/utils/map/marker_generator.dart:30:22)
	#10     buildMarkers (package:client/src/widget

@dnfield
Copy link
Contributor
dnfield commented Jun 14, 2021

That's a different problem and would be a bit more complicated to manage due to how these operations can access graphics contexts that can only be safely used on specific threads. Text layout on the other hand shoul dbe possible to do on any thread.

@danielgomezrico
Copy link
Contributor

😢 Got it, thanks for answering

@sagarkardani
Copy link

Can anyone update about the status of this issue ? I didn't find any update since long.

@Hixie Hixie changed the title Enable async text layout and painting. Enable dart:ui APIs for text measurement in secondary isolates Nov 11, 2021
@maxim-saplin
Copy link
maxim-saplin commented Dec 14, 2021

Thumbs up, I can alse see performance troubles (half a second freezes) when displaying not small (±20kb) strings as Rich text composed of a number of nested text spans. 70% of CPU time spent on layout

@dnfield
Copy link
Contributor
dnfield commented Dec 14, 2021

/cc @goderbauer fyi

@Liloupar
Copy link
Liloupar commented Jul 3, 2022

Can anyone update about the status of this issue ? this issue is open before 3 years.

@lpongetti
Copy link

+1

@dnfield
Copy link
Contributor
dnfield commented Oct 3, 2022

Another option for this would be to expose a lower-level text drawing API and just let people do layout/shaping via whatever aPI they in some other isolate/plugin and then send the glyph IDs/positions back to the UI isolate for drawing.

@Liloupar
Copy link
Liloupar commented Oct 5, 2022

Another option for this would be to expose a lower-level text drawing API and just let people do layout/shaping via whatever aPI they in some other isolate/plugin and then send the glyph IDs/positions back to the UI isolate for drawing.

Sounds like a great idea, like android StaticLayout.

@matthew-carroll
Copy link
Contributor

FYI - There are a couple areas of overlap between the problem described here, and some of the issues I described in #115257

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: typography Text rendering, possibly libtxt c: new feature Nothing broken; request for a new capability engine flutter/engine repository. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list team-engine Owned by Engine team triaged-engine Triaged by Engine team
Projects
None yet
Development

No branches or pull requests

0