Repository: flutter
Issue: Character width differs when specifying fonts directly or from ancestors using `TextSpan`
Labels: a: typography,has reproducible steps,P3,team-framework,triaged-framework,found in release: 3.19,found in release: 3.21

# Overview

I wanted to specify a particular font with `ThemeData.light()` as the base `TextTheme`, so I replaced only the font and recreated the `TextTheme`. However, I noticed that if the font style is inherited from the ancestor `TextTheme`, the width becomes slightly narrower than when the font style is specified directly. 

**Screenshot**

<img src="https://github.com/flutter/flutter/assets/12263798/4f317887-387d-40b6-9d90-ce4d4dca574b" width="320">

The images below are confirmation of the width of the Text widget in Flutter Inspector.

| Specify font from ancestor | Specify font directly |
----|---- 
| <img src="https://github.com/flutter/flutter/assets/12263798/f6ebcfec-95a5-48b2-922f-0b2ed3b9bf16" width="320"> | <img src="https://github.com/flutter/flutter/assets/12263798/1809e630-fe07-453a-8e9a-dae2d2b3c3f3" width="320"> |

Currently, this only occurs with numeral fonts and has been confirmed to occur only when using TextSpan.


<details>
<summary>  Smaple code </summary>

```dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  final baseFont = const TextStyle(
    fontSize: 24,
    color: Color(0xFFFC0D1C),
    fontWeight: FontWeight.bold,
    height: 1.1,
  );

  final text = '22,200';

  static TextStyle textStyleWithFontStyleApplied({TextStyle? baseTextStyle}) {
    assert(GoogleFonts.notoSansJp().fontFamily != null);
    return GoogleFonts.roboto(textStyle: baseTextStyle).copyWith(
      fontFamilyFallback: <String>[
        GoogleFonts.notoSansJp().fontFamily!,
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    final TextTheme lightTextTheme = ThemeData.light().textTheme;
    final textTheme = TextTheme(
      displayLarge: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.displayLarge,
      ),
      displayMedium: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.displayMedium,
      ),
      displaySmall: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.displaySmall,
      ),
      headlineLarge: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.headlineLarge,
      ),
      headlineMedium: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.headlineMedium,
      ),
      headlineSmall: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.headlineSmall,
      ),
      titleLarge: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.titleLarge,
      ),
      titleMedium: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.titleMedium,
      ),
      titleSmall: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.titleSmall,
      ),
      bodyLarge: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.bodyLarge,
      ),
      bodyMedium: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.bodyMedium,
      ),
      bodySmall: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.bodySmall,
      ),
      labelLarge: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.labelLarge,
      ),
      labelMedium: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.labelMedium,
      ),
      labelSmall: textStyleWithFontStyleApplied(
        baseTextStyle: lightTextTheme.labelSmall,
      ),
    );
    final themeData = Theme.of(context).copyWith(
      textTheme: textTheme,
    );
    return Theme(
      data: themeData,
      child: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text('Specify font from ancestor'),
              Text.rich(
                TextSpan(
                  children: [
                    TextSpan(
                      text: text,
                      style: baseFont,
                    ),
                  ],
                ),
              ),
              const Text('Specify font directly'),
              Text.rich(
                TextSpan(
                  children: [
                    TextSpan(
                      text: text,
                      style: textStyleWithFontStyleApplied(
                        baseTextStyle: baseFont,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

```



</details>

<details>
<summary>  pubspec.yaml </summary>

```yaml
name: try_roboto_font
description: "A new Flutter project."
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
  sdk: '>=3.2.0 <4.0.0'
dependencies:
  flutter:
    sdk: flutter
  google_fonts: ^6.1.0
  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
flutter:
  uses-material-design: true
```


</details>



<details>
<summary>  flutter doctor -v </summary>
```
➜  try_roboto_font git:(main) flutter doctor -v
[✓] Flutter (Channel stable, 3.16.0, on macOS 13.4 22F66 darwin-arm64, locale ja-JP)
    • Flutter version 3.16.0 on channel stable at /Users/01036096/fvm/versions/3.16.0
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision db7ef5bf9f (4 months ago), 2023-11-15 11:25:44 -0800
    • Engine revision 74d16627b9
    • Dart version 3.2.0
    • DevTools version 2.28.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /Users/01036096/Library/Android/sdk
    • Platform android-33, build-tools 33.0.2
    • ANDROID_HOME = /Users/01036096/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
    • Xcode at /Applications/Xcode14.1.app/Contents/Developer
    • Build 14B47b
    • CocoaPods version 1.12.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.2)
    • Android Studio at /Applications/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 17.0.6+0-17.0.6b802.4-9586694)

[✓] VS Code (version 1.86.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.84.0

[✓] Connected device (3 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64  • Android 12 (API 31) (emulator)
    • macOS (desktop)             • macos         • darwin-arm64   • macOS 13.4 22F66 darwin-arm64
    • Chrome (web)                • chrome        • web-javascript • Google Chrome 122.0.6261.112

[✓] Network resources
    • All expected network resources are available.

• No issues found!
```
</details>