ratex_flutter 0.1.4
ratex_flutter: ^0.1.4 copied to clipboard
Flutter bindings for RaTeX — native LaTeX math rendering via Dart FFI.
RaTeX — Flutter Integration Guide #
Native Flutter rendering of LaTeX math formulas via Dart FFI and CustomPainter. No WebView, no JavaScript.
How it works #
LaTeX string
↓ RaTeXFfi.parseAndLayout() [Dart FFI → libratex_ffi]
JSON DisplayList
↓ DisplayList.fromJson() [Dart JSON decode]
DisplayList
↓ RaTeXPainter.paint() [flutter/canvas]
CustomPaint Widget
Out of the box #
- Add dependency — add
ratex_flutter: ^0.1.4topubspec.yaml, then runflutter pub get. No native build required — the published package includes prebuilt Android.so, iOS XCFramework, macOS.dylib, Windows.dll, and Linux.so. - Register fonts — Flutter does not auto-register plugin fonts for the host app. Copy the KaTeX font declarations into your
pubspec.yaml(see Installation below). - Use — Use
RaTeXWidget:RaTeXWidget( latex: r'\frac{-b \pm \sqrt{b^2-4ac}}{2a}', fontSize: 28, onError: (e) => debugPrint('RaTeX: $e'), )
Installation #
From pub.dev (recommended) #
Add to your pubspec.yaml:
dependencies:
ratex_flutter: ^0.1.4
Then run flutter pub get. No native build required — the published package includes prebuilt Android .so, iOS RaTeX.xcframework, macOS .dylib, Windows .dll, and Linux .so.
Font setup
Flutter requires host apps to explicitly declare fonts from plugin packages (Flutter docs). Add the following to the flutter: section of your pubspec.yaml:
flutter:
fonts:
- family: KaTeX_AMS
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_AMS-Regular.ttf
- family: KaTeX_Caligraphic
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Caligraphic-Regular.ttf
- asset: packages/ratex_flutter/fonts/KaTeX_Caligraphic-Bold.ttf
weight: 700
- family: KaTeX_Fraktur
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Fraktur-Regular.ttf
- asset: packages/ratex_flutter/fonts/KaTeX_Fraktur-Bold.ttf
weight: 700
- family: KaTeX_Main
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Main-Regular.ttf
- asset: packages/ratex_flutter/fonts/KaTeX_Main-Bold.ttf
weight: 700
- asset: packages/ratex_flutter/fonts/KaTeX_Main-Italic.ttf
style: italic
- asset: packages/ratex_flutter/fonts/KaTeX_Main-BoldItalic.ttf
weight: 700
style: italic
- family: KaTeX_Math
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Math-Italic.ttf
style: italic
- asset: packages/ratex_flutter/fonts/KaTeX_Math-BoldItalic.ttf
weight: 700
style: italic
- family: KaTeX_SansSerif
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_SansSerif-Regular.ttf
- asset: packages/ratex_flutter/fonts/KaTeX_SansSerif-Bold.ttf
weight: 700
- asset: packages/ratex_flutter/fonts/KaTeX_SansSerif-Italic.ttf
style: italic
- family: KaTeX_Script
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Script-Regular.ttf
- family: KaTeX_Typewriter
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Typewriter-Regular.ttf
- family: KaTeX_Size1
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Size1-Regular.ttf
- family: KaTeX_Size2
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Size2-Regular.ttf
- family: KaTeX_Size3
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Size3-Regular.ttf
- family: KaTeX_Size4
fonts:
- asset: packages/ratex_flutter/fonts/KaTeX_Size4-Regular.ttf
Without this step, RaTeXPainter silently falls back to the system font and formulas render incorrectly.
From local path (development) #
If you use the package from the RaTeX repo:
dependencies:
ratex_flutter:
path: /path/to/RaTeX/platforms/flutter
You must build the native libraries first:
| Platform | Command |
|---|---|
| iOS | bash platforms/ios/build-ios.sh (produces RaTeX.xcframework) |
| Android | bash platforms/android/build-android.sh (produces .so files) |
| macOS | bash platforms/flutter/build-desktop.sh (produces universal .dylib) |
| Windows | bash platforms/flutter/build-desktop.sh --all from macOS/Linux (cross-compiles .dll via zigbuild) |
| Linux | bash platforms/flutter/build-desktop.sh --all from macOS/Linux (cross-compiles .so via zigbuild) |
Alternatively, run the desktop build on the target host directly:
# On macOS (builds universal dylib)
bash platforms/flutter/build-desktop.sh
# On Linux (builds host-arch .so)
bash platforms/flutter/build-desktop.sh
# On Windows (requires Git Bash / WSL; builds .dll)
bash platforms/flutter/build-desktop.sh
Prerequisites for building from source: Flutter 3.10+, Dart 3.0+, Rust 1.75+.
Usage #
Widget (recommended) #
import 'package:ratex_flutter/ratex_flutter.dart';
class MathPage extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
body: Center(
child: RaTeXWidget(
latex: r'\frac{-b \pm \sqrt{b^2-4ac}}{2a}',
fontSize: 28,
color: Colors.blue,
onError: (e) => debugPrint('RaTeX: $e'),
),
),
);
}
Low-level CustomPainter #
import 'package:flutter/material.dart';
import 'package:ratex_flutter/ratex_flutter.dart';
final dl = RaTeXEngine.instance.parseAndLayout(r'\sum_{n=1}^\infty \frac{1}{n^2}');
final blueDl = RaTeXEngine.instance.parseAndLayout(r'x + y', color: Colors.blue);
final painter = RaTeXPainter(displayList: dl, fontSize: 24);
// In a CustomPaint widget:
CustomPaint(painter: painter, size: Size(painter.widthPx, painter.totalHeightPx))
Inline formula (mixed text + LaTeX) #
Flutter's RichText + WidgetSpan is the recommended approach for mixing plain text with inline formulas. Use PlaceholderAlignment.middle for vertical centering:
import 'package:flutter/material.dart';
import 'package:ratex_flutter/ratex_flutter.dart';
/// Parses [text] with `$...$` inline math markers and returns a [RichText]
/// that intermixes plain [TextSpan]s with [WidgetSpan]s.
Widget buildInlineMath(String text, {double mathFontSize = 18, TextStyle? textStyle}) {
final style = textStyle ??
const TextStyle(fontSize: 16, height: 1.8, color: Colors.black87);
final parts = text.split(r'$');
final spans = <InlineSpan>[];
for (int i = 0; i < parts.length; i++) {
if (parts[i].isEmpty) continue;
if (i.isEven) {
// Plain text
spans.add(TextSpan(text: parts[i], style: style));
} else {
// Inline math
spans.add(WidgetSpan(
alignment: PlaceholderAlignment.middle,
baseline: TextBaseline.alphabetic,
child: RaTeXWidget(
latex: parts[i],
fontSize: mathFontSize,
onError: (e) => debugPrint('RaTeX inline error: $e'),
loading: const SizedBox.shrink(),
),
));
}
}
return RichText(text: TextSpan(children: spans));
}
// Usage:
buildInlineMath(
r'质能等价关系 $E = mc^2$,其中光速 $c \approx 3\times10^8\ \text{m/s}$。',
)
If RaTeXWidget.color is omitted, it inherits DefaultTextStyle.of(context).style.color and falls back to black.
Async (large formulas) #
import 'package:flutter/foundation.dart';
final dl = await compute(
(latex) => RaTeXEngine.instance.parseAndLayout(latex, color: Colors.blue),
r'\prod_{n=1}^\infty \left(1 - \frac{1}{n^2}\right)',
);
Coordinate system #
Same as iOS/Android: all coordinates are in em units, multiplied by fontSize
(logical pixels) to get screen coordinates. Y increases downward from the top of
the bounding box. The baseline is at Y = height × fontSize.
File map #
| File | Purpose |
|---|---|
pubspec.yaml |
Flutter plugin manifest |
ios/ |
iOS plugin (podspec + RaTeXPlugin.swift); links RaTeX.xcframework |
android/ |
Android plugin (RaTeXPlugin.kt); uses in-package jniLibs for libratex_ffi.so |
macos/ |
macOS plugin (podspec + RaTeXPlugin.swift); links universal .dylib |
windows/ |
Windows plugin (CMake + C++ stub); includes ratex_ffi.dll |
linux/ |
Linux plugin (CMake + GObject stub); includes per-arch libratex_ffi.so |
lib/ratex_flutter.dart |
Public API: RaTeXEngine, RaTeXWidget |
lib/src/display_list.dart |
Dart JSON types (DisplayList, DisplayItem, …) |
lib/src/ratex_ffi.dart |
Dart FFI bindings to libratex_ffi |
lib/src/ratex_painter.dart |
CustomPainter drawing loop |
Publishing to pub.dev (maintainers) #
To publish an out-of-the-box package that works without building native code:
-
Android — Build and copy JNI libs into the package:
# From repo root ./platforms/android/build-android.sh cp -R platforms/android/src/main/jniLibs/* platforms/flutter/android/src/main/jniLibs/ -
iOS — Ensure
RaTeX.xcframeworkis inside the package (not a symlink):# From repo root ./platforms/ios/build-ios.sh # If platforms/flutter/ios/RaTeX.xcframework is a symlink, replace with real copy: rm -rf platforms/flutter/ios/RaTeX.xcframework cp -R platforms/ios/RaTeX.xcframework platforms/flutter/ios/ -
Desktop — Build and inject platform-specific native libs:
# From repo root — cross-compile all desktop targets (requires zig + cargo-zigbuild) ./platforms/flutter/build-desktop.sh --all -
Validate and publish:
cd platforms/flutter dart pub publish --dry-run dart pub publishCI: Pushing a version tag (e.g.
v{VERSION}) runs release-flutter.yml: it builds Android, iOS, and desktop native libs, injects them into this package, and runsdart pub publish. Ensure the tag matches theversioninpubspec.yaml. Repository secret required:PUB_DEV_TOKEN(create at https://pub.dev/settings/tokens).