Reland #43118 "Add a flag to ParagraphBuilder for rounding hack migration" (flutter/engine#43647)

real diff: aedc37a3e0

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
LongCatIsLooong
2023-07-13 15:30:32 -07:00
committed by GitHub
parent 4e696fc84d
commit b7472f9a45
12 changed files with 154 additions and 11 deletions

View File

@@ -78,7 +78,7 @@ typedef CanvasPath Path;
V(Gradient::Create, 1) \
V(ImageFilter::Create, 1) \
V(ImageShader::Create, 1) \
V(ParagraphBuilder::Create, 9) \
V(ParagraphBuilder::Create, 10) \
V(PathMeasure::Create, 3) \
V(Path::Create, 1) \
V(PictureRecorder::Create, 1) \

View File

@@ -2798,7 +2798,7 @@ abstract class Paragraph {
/// This only returns a valid value if asserts are enabled, and must not be
/// used otherwise.
bool get debugDisposed;
}
}
@pragma('vm:entry-point')
base class _NativeParagraph extends NativeFieldWrapperClass1 implements Paragraph {
@@ -3015,6 +3015,28 @@ abstract class ParagraphBuilder {
/// [Paragraph].
factory ParagraphBuilder(ParagraphStyle style) = _NativeParagraphBuilder;
/// Whether the rounding hack enabled by default in SkParagraph and TextPainter
/// is disabled.
///
/// Do not rely on this getter as it exists for migration purposes only and
/// will soon be removed.
static bool get shouldDisableRoundingHack {
return const bool.hasEnvironment('SKPARAGRAPH_REMOVE_ROUNDING_HACK')
|| _roundingHackDisabledInDebugMode;
}
static bool _roundingHackDisabledInDebugMode = false;
/// Only works in debug mode. Do not call this method as it is for migration
/// purposes only and will soon be removed.
static void setDisableRoundingHack(bool disableRoundingHack) {
// bool.hasEnvironment does not work in internal tests so an additional flag
// is needed for tests.
assert(() {
_roundingHackDisabledInDebugMode = disableRoundingHack;
return true;
}());
}
/// The number of placeholders currently in the paragraph.
int get placeholderCount;
@@ -3132,11 +3154,12 @@ base class _NativeParagraphBuilder extends NativeFieldWrapperClass1 implements P
style._fontSize ?? 0,
style._height ?? 0,
style._ellipsis ?? '',
_encodeLocale(style._locale)
_encodeLocale(style._locale),
!ParagraphBuilder.shouldDisableRoundingHack,
);
}
@Native<Void Function(Handle, Handle, Handle, Handle, Handle, Double, Double, Handle, Handle)>(symbol: 'ParagraphBuilder::Create')
@Native<Void Function(Handle, Handle, Handle, Handle, Handle, Double, Double, Handle, Handle, Bool)>(symbol: 'ParagraphBuilder::Create')
external void _constructor(
Int32List encoded,
ByteData? strutData,
@@ -3145,7 +3168,8 @@ base class _NativeParagraphBuilder extends NativeFieldWrapperClass1 implements P
double fontSize,
double height,
String ellipsis,
String locale);
String locale,
bool applyRoundingHack);
@override
int get placeholderCount => _placeholderCount;

View File

@@ -151,11 +151,12 @@ void ParagraphBuilder::Create(Dart_Handle wrapper,
double fontSize,
double height,
const std::u16string& ellipsis,
const std::string& locale) {
const std::string& locale,
bool applyRoundingHack) {
UIDartState::ThrowIfUIOperationsProhibited();
auto res = fml::MakeRefCounted<ParagraphBuilder>(
encoded_handle, strutData, fontFamily, strutFontFamilies, fontSize,
height, ellipsis, locale);
height, ellipsis, locale, applyRoundingHack);
res->AssociateWithDartWrapper(wrapper);
}
@@ -230,7 +231,8 @@ ParagraphBuilder::ParagraphBuilder(
double fontSize,
double height,
const std::u16string& ellipsis,
const std::string& locale) {
const std::string& locale,
bool applyRoundingHack) {
int32_t mask = 0;
txt::ParagraphStyle style;
{
@@ -291,6 +293,7 @@ ParagraphBuilder::ParagraphBuilder(
if (mask & kPSLocaleMask) {
style.locale = locale;
}
style.apply_rounding_hack = applyRoundingHack;
FontCollection& font_collection = UIDartState::Current()
->platform_configuration()

View File

@@ -30,7 +30,8 @@ class ParagraphBuilder : public RefCountedDartWrappable<ParagraphBuilder> {
double fontSize,
double height,
const std::u16string& ellipsis,
const std::string& locale);
const std::string& locale,
bool applyRoundingHack);
~ParagraphBuilder() override;
@@ -76,7 +77,8 @@ class ParagraphBuilder : public RefCountedDartWrappable<ParagraphBuilder> {
double fontSize,
double height,
const std::u16string& ellipsis,
const std::string& locale);
const std::string& locale,
bool applyRoundingHack);
std::unique_ptr<txt::ParagraphBuilder> m_paragraphBuilder;
};

View File

@@ -2722,6 +2722,8 @@ extension SkParagraphStylePropertiesExtension on SkParagraphStyleProperties {
@JS('replaceTabCharacters')
external set _replaceTabCharacters(JSBoolean? bool);
set replaceTabCharacters(bool? bool) => _replaceTabCharacters = bool?.toJS;
external set applyRoundingHack(bool applyRoundingHack);
}
@JS()

View File

@@ -328,6 +328,7 @@ class CanvasKitRenderer implements Renderer {
strutStyle: strutStyle,
ellipsis: ellipsis,
locale: locale,
applyRoundingHack: !ui.ParagraphBuilder.shouldDisableRoundingHack,
);
@override

View File

@@ -33,6 +33,7 @@ class CkParagraphStyle implements ui.ParagraphStyle {
ui.StrutStyle? strutStyle,
String? ellipsis,
ui.Locale? locale,
bool applyRoundingHack = true,
}) : skParagraphStyle = toSkParagraphStyle(
textAlign,
textDirection,
@@ -46,6 +47,7 @@ class CkParagraphStyle implements ui.ParagraphStyle {
strutStyle,
ellipsis,
locale,
applyRoundingHack,
),
_fontFamily = _effectiveFontFamily(fontFamily),
_fontSize = fontSize,
@@ -145,6 +147,7 @@ class CkParagraphStyle implements ui.ParagraphStyle {
ui.StrutStyle? strutStyle,
String? ellipsis,
ui.Locale? locale,
bool applyRoundingHack,
) {
final SkParagraphStyleProperties properties = SkParagraphStyleProperties();
@@ -181,6 +184,7 @@ class CkParagraphStyle implements ui.ParagraphStyle {
properties.replaceTabCharacters = true;
properties.textStyle = toSkTextStyleProperties(
fontFamily, fontSize, height, fontWeight, fontStyle);
properties.applyRoundingHack = applyRoundingHack;
return canvasKit.ParagraphStyle(properties);
}

View File

@@ -685,6 +685,19 @@ abstract class Paragraph {
abstract class ParagraphBuilder {
factory ParagraphBuilder(ParagraphStyle style) =>
engine.renderer.createParagraphBuilder(style);
static bool get shouldDisableRoundingHack {
return const bool.hasEnvironment('SKPARAGRAPH_REMOVE_ROUNDING_HACK')
|| _roundingHackDisabledInDebugMode;
}
static bool _roundingHackDisabledInDebugMode = false;
static void setDisableRoundingHack(bool disableRoundingHack) {
assert(() {
_roundingHackDisabledInDebugMode = disableRoundingHack;
return true;
}());
}
void pushStyle(TextStyle style);
void pop();
void addText(String text);

View File

@@ -123,7 +123,51 @@ void testMain() {
}
});
});
test('applyRoundingHack works', () {
bool assertsEnabled = false;
assert(() {
assertsEnabled = true;
return true;
}());
if (!assertsEnabled){
return;
}
const double fontSize = 1.25;
const String text = '12345';
assert((fontSize * text.length).truncate() != fontSize * text.length);
final bool roundingHackWasDisabled = ui.ParagraphBuilder.shouldDisableRoundingHack;
ui.ParagraphBuilder.setDisableRoundingHack(true);
final ui.ParagraphBuilder builder = ui.ParagraphBuilder(
ui.ParagraphStyle(fontSize: fontSize, fontFamily: 'FlutterTest'),
);
builder.addText(text);
final ui.Paragraph paragraph = builder.build()
..layout(const ui.ParagraphConstraints(width: text.length * fontSize));
expect(paragraph.maxIntrinsicWidth, text.length * fontSize);
switch (paragraph.computeLineMetrics()) {
case [ui.LineMetrics(width: final double width)]:
expect(width, text.length * fontSize);
case final List<ui.LineMetrics> metrics:
expect(metrics, hasLength(1));
}
ui.ParagraphBuilder.setDisableRoundingHack(roundingHackWasDisabled);
});
test('rounding hack applied by default', () {
const double fontSize = 1.25;
const String text = '12345';
assert((fontSize * text.length).truncate() != fontSize * text.length);
expect(ui.ParagraphBuilder.shouldDisableRoundingHack, isFalse);
final ui.ParagraphBuilder builder = ui.ParagraphBuilder(ui.ParagraphStyle(fontSize: fontSize, fontFamily: 'FlutterTest'));
builder.addText(text);
final ui.Paragraph paragraph = builder.build()
..layout(const ui.ParagraphConstraints(width: text.length * fontSize));
expect(paragraph.computeLineMetrics().length, greaterThan(1));
});
// TODO(hterkelsen): https://github.com/flutter/flutter/issues/71520
}, skip: isSafari || isFirefox);
}

View File

@@ -233,4 +233,45 @@ void main() {
expect(callback, throwsStateError);
}
});
test('disableRoundingHack works in tests', () {
bool assertsEnabled = false;
assert(() {
assertsEnabled = true;
return true;
}());
if (!assertsEnabled){
return;
}
const double fontSize = 1.25;
const String text = '12345';
assert((fontSize * text.length).truncate() != fontSize * text.length);
final bool roundingHackWasDisabled = ParagraphBuilder.shouldDisableRoundingHack;
ParagraphBuilder.setDisableRoundingHack(true);
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(fontSize: fontSize));
builder.addText(text);
final Paragraph paragraph = builder.build()
..layout(const ParagraphConstraints(width: text.length * fontSize));
expect(paragraph.maxIntrinsicWidth, text.length * fontSize);
switch (paragraph.computeLineMetrics()) {
case [LineMetrics(width: final double width)]:
expect(width, text.length * fontSize);
case final List<LineMetrics> metrics:
expect(metrics, hasLength(1));
}
ParagraphBuilder.setDisableRoundingHack(roundingHackWasDisabled);
});
test('rounding hack applied by default', () {
const double fontSize = 1.25;
const String text = '12345';
assert((fontSize * text.length).truncate() != fontSize * text.length);
expect(ParagraphBuilder.shouldDisableRoundingHack, isFalse);
final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(fontSize: fontSize));
builder.addText(text);
final Paragraph paragraph = builder.build()
..layout(const ParagraphConstraints(width: text.length * fontSize));
expect(paragraph.computeLineMetrics().length, greaterThan(1));
});
}

View File

@@ -138,6 +138,7 @@ skt::ParagraphStyle ParagraphBuilderSkia::TxtToSkia(const ParagraphStyle& txt) {
skia.turnHintingOff();
skia.setReplaceTabCharacters(true);
skia.setApplyRoundingHack(txt.apply_rounding_hack);
return skia;
}

View File

@@ -95,6 +95,14 @@ class ParagraphStyle {
std::u16string ellipsis;
std::string locale;
// Temporary flag that indicates whether the Paragraph should report its
// metrics with rounding hacks applied.
//
// This flag currently defaults to true and will be flipped to false once the
// migration is complete.
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/31707
bool apply_rounding_hack = true;
TextStyle GetTextStyle() const;
bool unlimited_lines() const;