kashida
Flutter package for justifying Arabic and Syriac text with kashida
(tatweel, U+0640): find insertion points, wrap to a pixel width, fill by
priority, and paint with KashidaText.
Matching and measure-based layout live in kashida_core (sibling README). This package re-exports that API and adds Flutter measuring plus the widget.
Demo
Example app Justify tab: pick a face and a pattern set, then fill a width. The last line of each paragraph stays short unless Justify last line is on.

Features
KashidaText— justified block with cached layoutlayoutParagraphStyled/TextWidthCache— FlutterTextPaintermetrics- Optional
justifyLastLine— stretch the last line of each paragraph (off by default; see design notes) - Full kashida_core API via re-export
(patterns, find, insert,
layoutParagraph) - Example app (justify / find-and-insert / rules) with bundled OFL fonts
Getting started
dependencies:
kashida: ^0.1.2
import 'package:kashida/kashida.dart';
For CLI or server code without Flutter, use kashida_core.
Usage
Justify in a widget
final set = requiredBuiltinPatternSet('arabic-naskh');
KashidaText(
paragraph,
patternSet: set,
width: 320,
style: const TextStyle(fontSize: 22),
// justifyLastLine: true, // also stretch the last line of each paragraph
);
Or layout without a widget:
final lines = layoutParagraphStyled(
paragraph,
set,
const TextStyle(fontSize: 22),
width: 320,
// justifyLastLine: true,
);
Find points or insert a fixed count
final set = requiredBuiltinPatternSet('arabic-simple');
final found = findKashidaPoints('بيت', set);
for (final point in found.points) {
print('${point.priority} @ grapheme ${point.index}');
}
// Same tatweel count at every allowed join — not line justification.
print(insertKashida('بيت', set));
KashidaPoint.index is a grapheme index. Do not pass it to substring;
use point.endOffsetIn(text) or insertKashidaAt.
Custom rules and the pattern grammar are documented in kashida_core.
Layout behavior
- Greedy wrap on whitespace; a single over-wide word overflows
- Leftover space thinner than one tatweel is spread between words
(
MainAxisAlignment.spaceBetween) - Last line of each
\n-separated paragraph stays short unlessjustifyLastLine: true
More detail: doc/design.md.
Example app
cd example
flutter run
Acknowledgements
Port of raqim-kashida by Khaled Hosny and Alif Type. Any mistakes in the Dart implementation are ours.
Additional information
Issues and contributions are welcome. Include a small Arabic or Syriac sample and the pattern set name when reporting matching or justification bugs.
Libraries
- kashida
- Finding kashida (tatweel) insertion points and priorities, driven by a small pattern language.