flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.22k stars 27.27k forks source link

TextPainter draws out of position with very small fontSize #88747

Open safield opened 3 years ago

safield commented 3 years ago

Summary: When using a TextPainter to draw font that is very small (0.53 fontSize) on a highly scaled canvas (20x), the font will be positioned above the expected draw region.

Flutter 2.2.3 • channel stable • https://github.com/flutter/flutter.git Framework • revision f4abaa0735 (8 weeks ago) • 2021-07-01 12:46:11 -0700 Engine • revision 241c87ad80 Tools • Dart 2.13.4 Tested On Android 8.0 Moto G5 Plus

Reproduction Example:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        painter: TextPaintTester(),
        child: Container(),
      ),
    );
  }
}

class TextPaintTester extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    canvas.scale(20);

    var offset1 = Offset(4, 4);
    _paintText(canvas, offset1, 2.0); // positioned as expected

    var offset2 = Offset(4, 8);
    _paintText(canvas, offset2, 0.54); // positioned as expected

    var offset3 = Offset(4, 12);
    _paintText(canvas, offset3, 0.53); // unexpectedly position above expected region
  }

  static void _paintText(Canvas canvas, Offset offset, double fontSize) {
    canvas.drawCircle(offset, 0.1, Paint()..color = Colors.black);
    var span = new TextSpan(
      style: new TextStyle(
        color: Colors.black87,
        fontSize: fontSize,
      ),
      text: "Test Text",
    );
    TextPainter tp = new TextPainter(
      text: span,
      textDirection: TextDirection.ltr,
    );
    tp.layout();
    var rect = Rect.fromLTWH(offset.dx , offset.dy , tp.width , tp.height);
    canvas.drawRect(rect, Paint()..color = Colors.red.withOpacity(0.3));
    tp.paint(canvas, offset);
  }

  @override
  bool shouldRepaint(TextPaintTester oldDelegate) => true;
}
darshankawar commented 3 years ago

@safield Is this specifically for web ? as I see below after running flutter run -d chrome:

Screenshot 2021-08-24 at 3 12 03 PM

On mobile though, it shows up properly:

Screenshot 2021-08-24 at 3 15 03 PM
safield commented 3 years ago

@darshankawar

I am replicating it on Android.

darshankawar commented 3 years ago

Tested On Android 8.0 Moto G5 Plus

I see. I missed this to read. I tried on Samsung S10 but didn't see the same behavior:

Screenshot 2021-08-25 at 1 28 35 PM

Can you try on latest master too to see if it's consistent ? Thanks.

safield commented 3 years ago

I would recommend decresing the value from 0.53 to something lower on your samsung. Its possible the value varies by device.

safield commented 3 years ago

As a clear reproduction cases already exists, this bug should be moved off of "waiting for customer response". We have is repoduced on web and Moto g5 plus.

My job is done here.

darshankawar commented 3 years ago

I would recommend decreasing the value from 0.53 to something lower on your samsung. Its possible the value varies by device.

Yes, doing that was able to see the issue.

stable and master flutter doctor -v ``` [✓] Flutter (Channel stable, 2.2.3, on Mac OS X 10.15.4 19E2269 darwin-x64, locale en-GB) • Flutter version 2.2.3 at /Users/dhs/documents/fluttersdk/flutter • Framework revision f4abaa0735 (4 days ago), 2021-07-01 12:46:11 -0700 • Engine revision 241c87ad80 • Dart version 2.13.4 [✓] Android toolchain - develop for Android devices (Android SDK version 30) • Android SDK at /Users/dhs/Library/Android/sdk • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Users/dhs/Library/Android/sdk • Java binary at: /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.3, Build version 12C33 • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • Android Studio at /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.57.1) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (4 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 10 (API 29) • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.114 • No issues found! [✓] Flutter (Channel master, 2.5.0-7.0.pre.228, on Mac OS X 10.15.4 19E2269 darwin-x64, locale en-GB) • Flutter version 2.5.0-7.0.pre.228 at /Users/dhs/documents/fluttersdk/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision ac05e7e3fe (3 hours ago), 2021-08-25 00:41:06 -0400 • Engine revision a9efb963de • Dart version 2.15.0 (build 2.15.0-43.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 30) • Android SDK at /Users/dhs/Library/Android/sdk • Platform android-30, build-tools 30.0.3 • ANDROID_HOME = /Users/dhs/Library/Android/sdk • Java binary at: /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.5.1, Build version 12E507 • CocoaPods version 1.10.1 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • Android Studio at /Users/dhs/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/202.7486908/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) [✓] VS Code (version 1.57.1) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.21.0 [✓] Connected device (4 available) • SM G975F (mobile) • RZ8M802WY0X • android-arm64 • Android 10 (API 29) • iPhone 12 Pro Max (mobile) • A5473606-0213-4FD8-BA16-553433949729 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-3 (simulator) • macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.4 19E2269 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.114 ```
centy commented 8 months ago

TextPainter.heigh is == 0 after calling layout(), probably connected issue with this one.

KseniiaM commented 8 months ago

TextPainter.heigh is == 0 after calling layout(), probably connected issue with this one.

We were using textPainter.height for our calculations and it was producing the same weird results described in this ticket. It only returns int values, even though the property is double (so 2.0, 1.0 and 0.0 for big scaling). Using textPainter.getFullHeightForCaret instead solved our issues, but we are still waiting for the textpainter fix with all the other cases. So, if textpainter is using the heigh property for it's own calculations, this is likely what is causing an issue.