Tategaki(縦書き)
A comprehensive Flutter package for Japanese vertical text (縦書き) layout with advanced typography features.
Features
- Basic Vertical Text Layout: Top-to-bottom, right-to-left Japanese text rendering
- Ruby (Furigana): Phonetic guide text beside characters
- Kenten (圏点): Various styles of emphasis marks (sesame, circles, triangles, etc.)
- Tatechuyoko (縦中横): Horizontal text within vertical layout (for numbers, dates)
- Warichu (割注): Two-line inline annotations
- Text Decoration (傍線): Sideline decorations (single, double, wavy, dotted)
- Text Alignment (地付き/天付き): Line-level vertical alignment
TextAlignment.start(天付き): Align to topTextAlignment.center: Center alignment (default)TextAlignment.end(地付き): Align to bottom
- Text Selection: Interactive text selection with copy support
- Advanced Kinsoku Shori (禁則処理): Proper line breaking rules for Japanese typography
- Kerning: Advanced character spacing adjustments for professional typography
- Yakumono Adjustment (約物調整): Fine-tuned punctuation positioning
- Burasage-gumi (ぶら下げ組): Hanging punctuation at line ends
- Half-width punctuation (半角処理): Treats certain punctuation as 0.5 character width
- Gyoto indent (行頭括弧の字下げ): Indented opening brackets at line start
- Consecutive punctuation spacing: Tightened spacing between adjacent punctuation
- RichText Support: Multiple text styles, colors, and sizes in a single vertical text
- Figure Layout: Image placement with captions and text wrapping support
Related Packages
This package is part of the Japanese text layout suite:
| Package | Description |
|---|---|
| kinsoku | Core text processing (line breaking, character classification) |
| tategaki | Vertical text layout (this package) |
| yokogaki | Horizontal text layout (横書き) |
Quick Start
3ステップで縦書きテキストを表示:
// 1. Import
import 'package:tategaki/tategaki.dart';
// 2. Widget内で使用
VerticalText(
'こんにちは、世界!',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24),
),
)
ルビ付きの例:
VerticalText(
'日本語',
ruby: const [RubyText(startIndex: 0, length: 3, ruby: 'にほんご')],
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 32),
rubyStyle: TextStyle(fontSize: 14),
),
)
Platform Support
| Platform | Status | Notes |
|---|---|---|
| Android | ✅ Supported | All features |
| iOS | ✅ Supported | All features |
| Web | ✅ Supported | All features |
| Windows | ✅ Supported | All features |
| macOS | ✅ Supported | All features |
| Linux | ✅ Supported | All features |
Requirements:
- Flutter: ≥1.17.0
- Dart SDK: ≥3.10.3
Installation
Add this to your package's pubspec.yaml file:
dependencies:
tategaki: ^0.5.1
Then run:
flutter pub get
Usage
Basic Vertical Text
The simplest way to display vertical Japanese text:
import 'package:flutter/material.dart';
import 'package:tategaki/tategaki.dart';
VerticalText(
'これは縦書きテキストの例です。日本語の伝統的な文書では、このように縦書きで文字を配置します。',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24, color: Colors.black87),
characterSpacing: 4,
lineSpacing: 24,
),
maxHeight: 400, // Wrap to next line after 400px height
)
With Ruby (Furigana)
Add phonetic guides to your vertical text:
VerticalText(
'日本語',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 32, color: Colors.black87),
rubyStyle: TextStyle(fontSize: 14, color: Colors.blue),
),
ruby: const [
RubyText(startIndex: 0, length: 3, ruby: 'にほんご'),
],
)
With Kenten (Emphasis Dots)
Add emphasis marks to important text:
VerticalText(
'重要な内容です',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 28, color: Colors.black87),
characterSpacing: 6,
),
kenten: const [
Kenten(startIndex: 0, length: 2, style: KentenStyle.filledCircle),
],
)
Available kenten styles:
KentenStyle.sesame- ゴマ点 (•)KentenStyle.filledCircle- 黒丸 (●)KentenStyle.circle- 白丸 (○)KentenStyle.filledTriangle- 黒三角 (▲)KentenStyle.triangle- 白三角 (△)KentenStyle.doubleCircle- 二重丸 (◎)
With Text Alignment (地付き/天付き)
Control line-level vertical alignment:
VerticalText(
'地付きの例です。',
style: VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24),
alignment: TextAlignment.end, // 地付き - align to bottom
),
maxHeight: 400,
)
Auto Tatechuyoko (Horizontal Numbers)
Automatically convert 2-digit numbers to horizontal layout within vertical text:
VerticalText(
'令和06年12月25日',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 28, color: Colors.black87),
characterSpacing: 4,
),
autoTatechuyoko: true, // Automatically detects 06, 12, 25
)
Selectable Text
Enable text selection with copy support:
SelectableVerticalText(
'これは選択可能な縦書きテキストです。',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24),
),
maxHeight: 400,
)
SelectionArea Integration (Selection API)
Use SelectionAreaVerticalText inside SelectionArea to enable unified text selection across multiple widgets:
SelectionArea(
child: Row(
children: [
SelectableText('横書きテキスト'),
SelectionAreaVerticalText(
text: '縦書きテキスト',
style: VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24),
),
rubyList: [
RubyText(startIndex: 0, length: 2, ruby: 'たて'),
],
maxHeight: 300,
),
],
),
)
This allows seamless text selection that spans across vertical and horizontal text widgets.
Advanced Typography with Kerning and Yakumono
Enable professional Japanese typography features:
VerticalText(
'「これは、約物調整の例です。」と彼は言った。',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24, color: Colors.black87),
characterSpacing: 4,
enableKerning: true, // Adjust spacing between characters
enableHalfWidthYakumono: true, // Treat 。、as half-width
enableBurasageGumi: true, // Allow punctuation to hang
enableGyotoIndent: true, // Indent opening brackets
adjustYakumono: true, // Fine-tune punctuation positions
),
maxHeight: 400,
)
Kinsoku Processing (Line Breaking Rules)
Proper Japanese line breaking that respects forbidden positions:
VerticalText(
'これは禁則処理のデモです。行頭や行末に来てはいけない文字(句読点や括弧など)が適切に処理されます。',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 22, color: Colors.black87),
characterSpacing: 3,
lineSpacing: 20,
),
maxHeight: 300, // Kinsoku rules apply at line breaks
)
The package automatically:
- Prevents punctuation (。、!?) from appearing at line start
- Prevents opening brackets ((「【) from appearing at line end
- Keeps inseparable character pairs (…… ) together
RichText with Multiple Styles
Create vertical text with multiple fonts, colors, and sizes:
VerticalRichText(
textSpan: VerticalTextSpan(
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24, color: Colors.black87),
characterSpacing: 4,
),
children: [
const VerticalTextSpan(text: 'これは'),
VerticalTextSpan(
text: '強調された',
style: const VerticalTextStyle(
baseStyle: TextStyle(
fontSize: 24,
color: Colors.red,
fontWeight: FontWeight.bold,
),
characterSpacing: 4,
),
),
const VerticalTextSpan(text: 'テキスト'),
VerticalTextSpan(
text: 'です',
style: const VerticalTextStyle(
baseStyle: TextStyle(
fontSize: 28,
color: Colors.blue,
),
characterSpacing: 4,
),
),
],
),
maxHeight: 400,
)
Comprehensive Typography Example
Combine all features for professional Japanese text layout:
VerticalText(
'昭和(1926年)12月25日。「美しい日本語の組版」を実現する為に、様々な工夫が凝らされている。',
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 20, color: Colors.black87),
characterSpacing: 3,
lineSpacing: 18,
enableKerning: true,
enableHalfWidthYakumono: true,
enableBurasageGumi: true,
enableGyotoIndent: true,
adjustYakumono: true,
),
autoTatechuyoko: true,
maxHeight: 350,
)
Configuration Options
VerticalTextStyle
| Property | Type | Default | Description |
|---|---|---|---|
baseStyle |
TextStyle |
- | Base text style (font, size, color, etc.) |
characterSpacing |
double |
0 |
Vertical spacing between characters |
lineSpacing |
double |
0 |
Horizontal spacing between lines |
alignment |
TextAlignment |
center |
Line-level alignment (start/center/end) |
rotateLatinCharacters |
bool |
false |
Rotate Latin characters 90° |
adjustYakumono |
bool |
true |
Enable yakumono position adjustments |
enableKerning |
bool |
false |
Enable advanced kerning |
enableHalfWidthYakumono |
bool |
false |
Treat certain punctuation as half-width |
enableBurasageGumi |
bool |
false |
Allow hanging punctuation at line ends |
enableGyotoIndent |
bool |
false |
Indent opening brackets at line start |
rubyStyle |
TextStyle? |
null |
Style for ruby (furigana) text |
Advanced Features
Custom Tatechuyoko
Manually specify tatechuyoko ranges:
VerticalText(
'AB月CD日',
tatechuyoko: const [
Tatechuyoko(startIndex: 0, length: 2), // AB
Tatechuyoko(startIndex: 3, length: 2), // CD
],
)
Figure Layout
Place images within vertical text with captions:
VerticalText(
'本文テキスト',
figures: [
Figure(
child: Image.asset('image.png'),
position: 10,
alignment: FigureAlignment.center,
caption: '図1:説明文',
),
],
)
Examples
Check out the /example directory for a comprehensive demo app showcasing all features.
To run the example:
cd example
flutter run
Implementation Details
Architecture
- CustomPainter-based: Uses Flutter's CustomPainter for precise character positioning and rotation
- Character-level layout: Each character is individually positioned and rotated according to Japanese typography rules
- Advanced line breaking: Implements proper kinsoku shori (禁則処理) with look-ahead and backtracking
- Modular design: Separate utilities for character classification, rotation rules, kerning, and punctuation adjustment
Typography Rules
The package implements proper Japanese typography rules following the W3C Japanese Text Layout Requirements:
- Character rotation for brackets, quotes, and dashes
- Small kana (っゃゅょ) size and position adjustment
- Punctuation width and position fine-tuning
- Proper line breaking with forbidden positions
- Character pair kerning for professional spacing
Use Cases / ユースケース
小説・文芸作品
縦書きの小説ビューアに最適:
VerticalText(
'吾輩は猫である。名前はまだ無い。'
'どこで生まれたかとんと見当がつかぬ。',
style: VerticalTextStyle(
baseStyle: TextStyle(
fontSize: 18,
fontFamily: 'NotoSerifJP', // 明朝体推奨
height: 1.8,
),
lineSpacing: 24,
characterSpacing: 2,
),
maxHeight: 500,
)
俳句・短歌
一行で表示する短詩形式:
VerticalText(
'古池や蛙飛び込む水の音',
ruby: const [
RubyText(startIndex: 0, length: 2, ruby: 'ふるいけ'),
RubyText(startIndex: 3, length: 1, ruby: 'かわず'),
],
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 28),
rubyStyle: TextStyle(fontSize: 12),
characterSpacing: 8,
),
)
新聞・雑誌レイアウト
見出しと本文の組み合わせ:
Column(
children: [
VerticalText(
'本日の主要ニュース',
style: const VerticalTextStyle(
baseStyle: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
),
VerticalText(
'詳細な本文がここに続きます...',
kenten: const [
Kenten(startIndex: 0, length: 2, style: KentenStyle.sesame),
],
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 16),
lineSpacing: 16,
),
maxHeight: 300,
),
],
)
年賀状・挨拶状
日付に縦中横を使用:
VerticalText(
'令和07年01月01日 謹賀新年',
autoTatechuyoko: true, // 07, 01 が横組みに
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 24),
characterSpacing: 4,
),
)
教育アプリ
選択可能なテキストで読解練習:
SelectableVerticalText(
'漢字の読み方を学びましょう。',
ruby: const [
RubyText(startIndex: 0, length: 2, ruby: 'かんじ'),
RubyText(startIndex: 3, length: 2, ruby: 'よみかた'),
],
style: const VerticalTextStyle(
baseStyle: TextStyle(fontSize: 28),
rubyStyle: TextStyle(fontSize: 14, color: Colors.blue),
),
maxHeight: 400,
)
Performance
tategaki v0.2.0+ includes significant performance optimizations:
- TextPainter Reuse: Reduced memory allocations by reusing TextPainter instances across renders
- Efficient Layout: Character layout caching for optimal performance
- Lazy Rendering: CustomPainter-based rendering with minimal overhead
- Memory Efficient: Low memory footprint even for long vertical texts
Performance improvements in v0.2.0:
- ~50% reduction in TextPainter allocations
- Improved rendering performance for scrollable vertical text lists
- Reduced memory pressure during text rendering
Roadmap
xBasic vertical text layoutxRuby (furigana) supportxKenten (emphasis dots) supportxTatechuyoko (horizontal in vertical)xAdvanced kinsoku processingxProfessional kerningxAdvanced yakumono adjustmentxRichText support with multiple stylesxComprehensive unit testsxPerformance optimizations (v0.2.0)xText selection with context menu (v0.3.0)xText alignment (地付き/天付き) (v0.4.0)xText decoration (sideline) supportxSelection API integration (SelectionArea support)Text editing support (planned)PDF export (planned)Web optimization (planned)
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
Development Setup
git clone https://github.com/youichi-uda/tategaki.git
cd tategaki
flutter pub get
flutter test
License
MIT License - see the LICENSE file for details.
Credits
Created by Youichi Uda
Special thanks to the Flutter community and the W3C Japanese Layout Task Force for their comprehensive documentation on Japanese typography.
References
- W3C Japanese Text Layout Requirements
- JIS X 4051:2004 - Japanese document composition method
- Flutter CustomPainter
Libraries
- tategaki
- A comprehensive Flutter package for Japanese vertical text (tategaki) layout with advanced typography features.