Skip to content

Commit

Permalink
Use plain Uint32List objects with the fragmenter APIs. (flutter#40239)
Browse files Browse the repository at this point in the history
Use plain Uint32List objects with the fragmenter APIs.
  • Loading branch information
eyebrowsoffire committed Mar 13, 2023
1 parent 3d545ad commit 7c5a9d5
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 33 deletions.
12 changes: 6 additions & 6 deletions lib/web_ui/lib/src/engine/canvaskit/canvaskit_api.dart
Expand Up @@ -1911,12 +1911,12 @@ extension SkParagraphBuilderExtension on SkParagraphBuilder {
// into a utf16 string.
String getText() => utf8.decode(getTextUtf8().codeUnits);

external void setWordsUtf8(SkUint32List words);
external void setWordsUtf16(SkUint32List words);
external void setGraphemeBreaksUtf8(SkUint32List graphemes);
external void setGraphemeBreaksUtf16(SkUint32List graphemes);
external void setLineBreaksUtf8(SkUint32List lineBreaks);
external void setLineBreaksUtf16(SkUint32List lineBreaks);
external void setWordsUtf8(Uint32List words);
external void setWordsUtf16(Uint32List words);
external void setGraphemeBreaksUtf8(Uint32List graphemes);
external void setGraphemeBreaksUtf16(Uint32List graphemes);
external void setLineBreaksUtf8(Uint32List lineBreaks);
external void setLineBreaksUtf16(Uint32List lineBreaks);

external SkParagraph build();
external void delete();
Expand Down
14 changes: 5 additions & 9 deletions lib/web_ui/lib/src/engine/canvaskit/text_fragmenter.dart
Expand Up @@ -43,7 +43,7 @@ final Map<IntlSegmenterGranularity, DomSegmenter> _intlSegmenters = <IntlSegment
IntlSegmenterGranularity.word: createIntlSegmenter(granularity: 'word'),
};

SkUint32List fragmentUsingIntlSegmenter(
Uint32List fragmentUsingIntlSegmenter(
String text,
IntlSegmenterGranularity granularity,
) {
Expand All @@ -55,10 +55,7 @@ SkUint32List fragmentUsingIntlSegmenter(
breaks.add(iterator.current.index);
}
breaks.add(text.length);

final SkUint32List mallocedList = mallocUint32List(breaks.length);
mallocedList.toTypedArray().setAll(0, breaks);
return mallocedList;
return Uint32List.fromList(breaks);
}

// These are the soft/hard line break values expected by Skia's SkParagraph.
Expand All @@ -67,13 +64,12 @@ const int _kHardLineBreak = 1;

final DomV8BreakIterator _v8LineBreaker = createV8BreakIterator();

SkUint32List fragmentUsingV8LineBreaker(String text) {
Uint32List fragmentUsingV8LineBreaker(String text) {
final List<LineBreakFragment> fragments =
breakLinesUsingV8BreakIterator(text, _v8LineBreaker);

final int size = (fragments.length + 1) * 2;
final SkUint32List mallocedList = mallocUint32List(size);
final Uint32List typedArray = mallocedList.toTypedArray();
final Uint32List typedArray = Uint32List(size);

typedArray[0] = 0; // start index
typedArray[1] = _kSoftLineBreak; // break type
Expand All @@ -87,5 +83,5 @@ SkUint32List fragmentUsingV8LineBreaker(String text) {
: _kSoftLineBreak;
}

return mallocedList;
return typedArray;
}
30 changes: 12 additions & 18 deletions lib/web_ui/test/canvaskit/text_fragmenter_test.dart
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
Expand All @@ -15,33 +17,25 @@ void main() {
void testMain() {
setUpCanvasKitTest();

late SkUint32List breaks;

tearDown(() {
if (browserSupportsCanvaskitChromium) {
free(breaks);
}
});

group('$fragmentUsingIntlSegmenter', () {
test('fragments text into words', () {
breaks = fragmentUsingIntlSegmenter(
final Uint32List breaks = fragmentUsingIntlSegmenter(
'Hello world 你好世界',
IntlSegmenterGranularity.word,
);
expect(
breaks.toTypedArray(),
breaks,
orderedEquals(<int>[0, 5, 6, 11, 12, 14, 16]),
);
});

test('fragments multi-line text into words', () {
breaks = fragmentUsingIntlSegmenter(
final Uint32List breaks = fragmentUsingIntlSegmenter(
'Lorem ipsum\ndolor 你好世界 sit\namet',
IntlSegmenterGranularity.word,
);
expect(
breaks.toTypedArray(),
breaks,
orderedEquals(<int>[
0, 5, 6, 11, 12, // "Lorem ipsum\n"
17, 18, 20, 22, 23, 26, 27, // "dolor 你好世界 sit\n"
Expand All @@ -53,12 +47,12 @@ void testMain() {
test('fragments text into grapheme clusters', () {
// The smiley emoji has a length of 2.
// The family emoji has a length of 11.
breaks = fragmentUsingIntlSegmenter(
final Uint32List breaks = fragmentUsingIntlSegmenter(
'Lorem🙂ipsum👨‍👩‍👧‍👦',
IntlSegmenterGranularity.grapheme,
);
expect(
breaks.toTypedArray(),
breaks,
orderedEquals(<int>[
0, 1, 2, 3, 4, 5, 7, // "Lorem🙂"
8, 9, 10, 11, 12, 23, // "ipsum👨‍👩‍👧‍👦"
Expand All @@ -69,12 +63,12 @@ void testMain() {
test('fragments multi-line text into grapheme clusters', () {
// The smiley emojis have a length of 2 each.
// The family emoji has a length of 11.
breaks = fragmentUsingIntlSegmenter(
final Uint32List breaks = fragmentUsingIntlSegmenter(
'Lorem🙂\nipsum👨‍👩‍👧‍👦dolor\n😄',
IntlSegmenterGranularity.grapheme,
);
expect(
breaks.toTypedArray(),
breaks,
orderedEquals(<int>[
0, 1, 2, 3, 4, 5, 7, 8, // "Lorem🙂\n"
9, 10, 11, 12, 13, 24, // "ipsum👨‍👩‍👧‍👦"
Expand All @@ -89,11 +83,11 @@ void testMain() {
const int kHard = 1;

test('fragments text into soft and hard line breaks', () {
breaks = fragmentUsingV8LineBreaker(
final Uint32List breaks = fragmentUsingV8LineBreaker(
'Lorem-ipsum 你好🙂\nDolor sit',
);
expect(
breaks.toTypedArray(),
breaks,
orderedEquals(<int>[
0, kSoft,
6, kSoft, // "Lorem-"
Expand Down

0 comments on commit 7c5a9d5

Please sign in to comment.