typeset 0.1.0
縦書き・横書きの日本語組版ライブラリ(JLReq 水準、ラスタ / PDF / SVG)
読み取り中…
検索中…
一致する文字列を見つけられません
paragraph.hpp
[詳解]
1#ifndef TYPESET_INL_PARAGRAPH_HPP
2#define TYPESET_INL_PARAGRAPH_HPP
3
4#include <map>
5#include <memory>
6#include <optional>
7#include <string>
8#include <vector>
9
15#include "typeset/style.hpp"
17
28namespace typeset::inl {
29
30struct Paragraph;
31
33struct ObjectRef {
34 std::string handler;
35 std::u16string source;
36 std::map<std::string, std::string> params;
37};
38
40struct InlineRun {
41 std::u16string text;
43 std::shared_ptr<const dl::Image> image;
45 std::shared_ptr<const obj::ObjectResult> object;
46 std::optional<ObjectRef> objectRef;
48 std::shared_ptr<const Paragraph> footnote;
50 bool literal = false;
52 bool placeholder = false;
53 std::string placeholderId;
54};
55
56struct Paragraph {
57 std::vector<InlineRun> runs;
58 std::vector<Annotation> annotations;
60
61 std::u16string text() const;
63 const TextStyle& baseStyle() const;
64
65 static Paragraph plain(std::u16string text, TextStyle style, ParagraphStyle pstyle = {}) {
66 Paragraph p;
67 p.runs.push_back(InlineRun{std::move(text), std::move(style)});
68 p.style = std::move(pstyle);
69 return p;
70 }
71
73 void addImage(std::shared_ptr<const dl::Image> image, Size size, TextStyle style) {
74 InlineRun r;
75 r.text = u"\uFFFC";
76 r.style = std::move(style);
77 r.image = std::move(image);
78 r.imageSize = size;
79 runs.push_back(std::move(r));
80 }
81
87 void addPlaceholder(Size size, TextStyle style, std::string id = std::string()) {
88 InlineRun r;
89 r.text = u"\uFFFC";
90 r.style = std::move(style);
91 r.placeholder = true;
92 r.placeholderId = std::move(id);
93 r.imageSize = size;
94 runs.push_back(std::move(r));
95 }
96
98 void addObject(std::string handler, std::u16string source, std::map<std::string, std::string> params,
100 InlineRun r;
101 r.text = u"\uFFFC";
102 r.style = std::move(style);
103 r.objectRef = ObjectRef{std::move(handler), std::move(source), std::move(params)};
104 runs.push_back(std::move(r));
105 }
107 void addObject(std::shared_ptr<const obj::ObjectResult> object, TextStyle style) {
108 InlineRun r;
109 r.text = u"\uFFFC";
110 r.style = std::move(style);
111 r.object = std::move(object);
112 runs.push_back(std::move(r));
113 }
114
119 void addFootnote(Paragraph note, TextStyle markerStyle);
120};
121
124 s.size *= 0.6f;
125 s.baselineShift = 0.6f;
126 return s;
127}
128
129inline void Paragraph::addFootnote(Paragraph note, TextStyle markerStyle) {
130 InlineRun r;
131 r.text = u"{fn}";
132 r.style = std::move(markerStyle);
133 r.footnote = std::make_shared<Paragraph>(std::move(note));
134 runs.push_back(std::move(r));
135}
136
138dl::Group objectGroup(const obj::ObjectResult& ob, const Rect& box, bool sideways);
139
143struct LineBox {
144 std::vector<PlacedGlyph> glyphs;
145 Pt length = 0.0f;
147 Pt blockMin = 0.0f;
148 Pt blockMax = 0.0f;
149 size_t charStart = 0;
150 size_t charEnd = 0;
151 bool hanging = false;
152 Pt hangWidth = 0.0f;
153 bool hyphenated = false;
154 int lineIndex = 0;
155 Pt indent = 0.0f;
156 bool paragraphEnd = false;
161};
162
170
172 std::vector<LineBox> lines;
173 std::vector<TextStyle> styles;
174 std::vector<StyleMetrics> styleMetrics;
175 std::vector<std::string> placeholderIds;
176 std::vector<bool> placeholders;
177 size_t charStart = 0;
178 size_t charEnd = 0;
179 bool complete = false;
180 Pt linePitch = 0.0f;
181 float rotation = 0.0f;
182 Pt baseSize = 0.0f;
183 std::shared_ptr<const std::u16string> text;
184
186 Pt lineAdvance(size_t li) const {
187 return linePitch + lines[li].extraBefore + lines[li].extraAfter;
188 }
190 Pt lineCenterOffset(size_t li) const {
191 Pt off = 0.0f;
192 for (size_t j = 0; j < li && j < lines.size(); ++j) off += lineAdvance(j);
193 return off + (li < lines.size() ? lines[li].extraBefore : 0.0f);
194 }
196 Pt blockExtent() const {
197 Pt s = 0.0f;
198 for (size_t j = 0; j < lines.size(); ++j) s += lineAdvance(j);
199 return s;
200 }
201};
202
204public:
205 explicit ParagraphLayouter(font::FontSet& fonts) : fonts_(fonts) {}
206
216 const LineShapeProvider& shape,
217 size_t charStart = 0, int maxLines = -1,
218 int firstLineIndex = 0);
219
220private:
221 ParagraphFragment layoutOnce(const Paragraph& para, WritingMode wm,
222 const LineShapeProvider& shape,
223 size_t charStart, int maxLines, int firstLineIndex);
224 void applyEllipsis(ParagraphFragment& frag, const Paragraph& para, WritingMode wm,
225 const LineShapeProvider& shape);
226 font::FontSet& fonts_;
227 std::vector<Pt> lineIndents_;
228};
229
235Point lineOrigin(WritingMode wm, Point origin, int lineOffset, Pt linePitch, Pt indent);
237Point lineOriginAt(WritingMode wm, Point origin, Pt adv, Pt indent);
238
247 Point origin, int lineOffset = 0, size_t maxChars = static_cast<size_t>(-1));
248
249//------------------------------------------------------------------------------
250// 取り出し口(ホストがリンク・ヒットテスト・キャレット・段階表示を作るための問い合わせ)
251//------------------------------------------------------------------------------
252
256struct CharBox {
257 size_t lineIndex = 0;
258 uint32_t charIndex = 0;
260 Pt inlineEnd = 0.0f;
261 Pt blockMin = 0.0f;
262 Pt blockMax = 0.0f;
263 uint32_t styleIndex = 0;
264 uint32_t gid = 0;
265 Pt size = 0.0f;
266 std::shared_ptr<glyphware::Face> face;
267 bool image = false;
268 bool object = false;
269 bool placeholder = false;
272};
273
275std::vector<CharBox> charBoxes(const ParagraphFragment& frag, WritingMode wm, size_t lineIndex);
276
278Point lineOriginOf(const ParagraphFragment& frag, WritingMode wm, Point origin, size_t lineIndex,
279 int lineOffset = 0);
280
285std::vector<Rect> rectsFor(const ParagraphFragment& frag, WritingMode wm, Point origin,
286 size_t charStart, size_t charEnd, int lineOffset = 0);
287
290 std::string id;
291 uint32_t charIndex = 0;
293};
294std::vector<PlaceholderRect> placeholderRects(const ParagraphFragment& frag, WritingMode wm, Point origin,
295 int lineOffset = 0);
296
300struct HitResult {
301 size_t lineIndex = 0;
302 uint32_t charIndex = 0;
303 bool inside = false;
304 bool after = false;
305};
307std::optional<HitResult> hitTest(const ParagraphFragment& frag, WritingMode wm, Point origin, Point p,
308 int lineOffset = 0);
309
314std::optional<Rect> caretRect(const ParagraphFragment& frag, WritingMode wm, Point origin, size_t charIndex,
315 int lineOffset = 0, Pt thickness = 1.0f);
316
322 BlockAlign blockAlign = BlockAlign::Start, Align align = Align::Start);
323
327struct FitResult {
329 float scale = 1.0f;
330 bool fits = true;
331};
333 const LineShapeProvider& shape, int maxLines,
334 float minScale = 0.5f, float step = 0.05f);
335
340 Pt advance = 0.0f;
341 Pt ascent = 0.0f;
342 Pt descent = 0.0f;
343 size_t clusterCount = 0;
344 size_t glyphCount = 0;
345};
346TextMetrics measureText(font::FontSet& fonts, const std::u16string& text, const TextStyle& style,
349
350} // namespace typeset::inl
351
352#endif // TYPESET_INL_PARAGRAPH_HPP
ParagraphLayouter(font::FontSet &fonts)
ParagraphFragment layout(const Paragraph &para, WritingMode wm, const LineShapeProvider &shape, size_t charStart=0, int maxLines=-1, int firstLineIndex=0)
段落を組む
inl/annotation — 行内に組み込む注記
std::optional< Rect > caretRect(const ParagraphFragment &frag, WritingMode wm, Point origin, size_t charIndex, int lineOffset=0, Pt thickness=1.0f)
キャレット矩形: charIndex の文字の始端(charIndex が行末なら最後の文字の終端)に、行送り方向の em の高さで thickness 幅の矩形。文字が無い(範囲外)なら nullop...
Point lineOriginAt(WritingMode wm, Point origin, Pt adv, Pt indent)
行送り方向に adv 進んだ行頭
std::optional< HitResult > hitTest(const ParagraphFragment &frag, WritingMode wm, Point origin, Point p, int lineOffset=0)
行送りの箱の範囲に無い点は nullopt。行の前後の余白は最も近い文字(行頭/行末)に丸める
std::vector< CharBox > charBoxes(const ParagraphFragment &frag, WritingMode wm, size_t lineIndex)
行 lineIndex の文字の箱(送り方向の順。注記のグリフは含めない。wm は画像の箱の向きに使う)
std::vector< PlaceholderRect > placeholderRects(const ParagraphFragment &frag, WritingMode wm, Point origin, int lineOffset=0)
Point lineOriginOf(const ParagraphFragment &frag, WritingMode wm, Point origin, size_t lineIndex, int lineOffset=0)
行 lineIndex の行頭(物理)。emitParagraph と同じ origin / lineOffset を渡す
FitResult fitParagraph(ParagraphLayouter &layouter, const Paragraph &para, WritingMode wm, const LineShapeProvider &shape, int maxLines, float minScale=0.5f, float step=0.05f)
dl::Group objectGroup(const obj::ObjectResult &ob, const Rect &box, bool sideways)
オブジェクトの描画命令を物理矩形 box に置く Group を作る(sideways: 時計回り 90° で横倒し)
TextMetrics measureText(font::FontSet &fonts, const std::u16string &text, const TextStyle &style, WritingMode wm=WritingMode::HorizontalTb, TextOrientation orientation=TextOrientation::Mixed)
Point originInBox(const ParagraphFragment &frag, WritingMode wm, const Rect &box, BlockAlign blockAlign=BlockAlign::Start, Align align=Align::Start)
箱の中での段落の位置: 行送り方向に blockAlign、行の方向に align(Justify は Start 扱い)で揃えた origin (emitParagraph に渡す 1 行目の行頭)を...
Point lineOrigin(WritingMode wm, Point origin, int lineOffset, Pt linePitch, Pt indent)
行 i の行頭(中心線上の点)の物理位置
TextStyle superscriptStyle(TextStyle s)
上付き(脚注記号・指数用): 0.6 倍にして注記側へ 0.6em ずらす
std::vector< Rect > rectsFor(const ParagraphFragment &frag, WritingMode wm, Point origin, size_t charStart, size_t charEnd, int lineOffset=0)
文字範囲 [charStart, charEnd) を覆う矩形(行ごとに 1 つ。物理座標。縦組みは縦長)。 リンクの当たり判定・選択範囲の描画用。範囲に文字が無い行は出ない
void emitParagraph(dl::DisplayList &out, const ParagraphFragment &frag, WritingMode wm, Point origin, int lineOffset=0, size_t maxChars=static_cast< size_t >(-1))
段落を表示リストへ出す
BlockAlign
行送り方向の揃え(箱の中での段落の位置。inl::originInBox)
Definition style.hpp:242
float Pt
Definition geom.hpp:17
TextOrientation
縦組み中の文字の正立/横倒し(CSS text-orientation 相当)
@ Mixed
和文は正立、欧文は横倒し(既定)
@ HorizontalTb
横組み
段落スタイル
Definition style.hpp:258
文字スタイル
Definition style.hpp:86
float baselineShift
ベースラインのずらし(このスタイルの em 単位)。注記側が正(横組み: 上、縦組み: 右)。上付き文字・脚注記号用
Definition style.hpp:116
1 ページ分の表示リスト
変形・クリップ・不透明度のスコープ
下線・打消し線のメトリクス(pt、size で換算)。位置はベースラインからの距離で下が正 (横組みの block 軸と同じ向き。打消し線は通常負)
Definition font_set.hpp:180
組んだあとの 1 文字(クラスタのグリフ 1 つ)の箱。注記のグリフは含めない
Rect rect(WritingMode wm, Point lineOrigin) const
物理座標での矩形
size_t lineIndex
ParagraphFragment::lines の添字
Pt inlineStart
箱の始端(行頭から。indent は含まない)
uint32_t charIndex
元テキストでの位置(UTF-16)
Pt inlineEnd
箱の終端
std::shared_ptr< glyphware::Face > face
Pt blockMin
箱の block 範囲(中心線から。em box、画像・オブジェクトはその大きさ)
自動縮小: 行数上限に収まるまで文字サイズ(と linePitch)を段階的に縮めて組み直す
float scale
採用した倍率(1 なら縮めていない)
ParagraphFragment fragment
bool fits
minScale まで縮めても収まらなければ false(fragment は minScale の結果)
uint32_t charIndex
当たった文字(行の後ろの余白なら行末 = line.charEnd)
bool inside
文字の箱の中に当たったか(false なら行の端に丸めた)
bool after
箱の後半に当たった(キャレットを次の文字の前に置く判断用)
スタイルの付いたテキスト片。image / object / objectRef が付いていれば行内オブジェクト(text は U+FFFC 1 文字)
Definition paragraph.hpp:40
bool literal
true なら {name} の置換や {index:} の収集をしない(コードなど、波括弧をそのまま出す run)
Definition paragraph.hpp:50
Size imageSize
pt。0 なら画素数を 72dpi として使い、片方 0 なら縦横比を保つ
Definition paragraph.hpp:44
std::shared_ptr< const dl::Image > image
Definition paragraph.hpp:43
std::shared_ptr< const obj::ObjectResult > object
解決済みのオブジェクト
Definition paragraph.hpp:45
bool placeholder
行内プレースホルダ(大きさ imageSize の空箱。描かない。ホストがウィジェット等を重ねる)
Definition paragraph.hpp:52
std::optional< ObjectRef > objectRef
未解決(FlowLayouter が解決する)
Definition paragraph.hpp:46
std::shared_ptr< const Paragraph > footnote
脚注。この run が本文中の記号(text は "{fn}"。FlowLayouter が番号に置き換え、段末に注を置く)
Definition paragraph.hpp:48
std::u16string text
Definition paragraph.hpp:41
std::string placeholderId
Definition paragraph.hpp:53
確定した 1 行(論理座標)
Pt naturalLength
調整前の行長
std::vector< PlacedGlyph > glyphs
inline_ は行頭から、block は中心線から
Pt extraBefore
行内オブジェクト/画像が行送りの箱 [-pitch/2, +pitch/2] から出るぶんの追加の送り(TeX の lineskip 相当)。 ルビや横倒しの張り出しでは広げない(行間に収める)
Pt length
調整後の行長
Pt indent
行頭の下げ(一字下げ+揃えによるシフト)
Pt blockMax
同(正側)
bool paragraphEnd
この行で(改行または本文の終わりで)段落が終わる
bool hanging
行末の約物を版面外へ出した(ぶら下げた)行か
size_t charStart
元テキストでの範囲(UTF-16)
int lineIndex
LineShapeProvider の行番号
bool hyphenated
欧文の単語をハイフンで割った行か(行末にハイフンのグリフが入る)
Pt blockMin
中心線からの張り出し(負側。ルビが横組みで上へ出る等)
外部ハンドラで生成するオブジェクトの指定(組版時に obj::ObjectRegistry で解決する)
Definition paragraph.hpp:33
std::map< std::string, std::string > params
Definition paragraph.hpp:36
std::u16string source
Definition paragraph.hpp:35
Pt lineAdvance(size_t li) const
行 li が占める行送り方向の量(行送り+行内オブジェクトのための追加)
std::vector< bool > placeholders
styles と同じ添字。プレースホルダの run か
std::shared_ptr< const std::u16string > text
元テキスト(ToUnicode 用)
std::vector< std::string > placeholderIds
styles と同じ添字。プレースホルダの run だけ非空(id 未指定なら "")
Pt lineCenterOffset(size_t li) const
行 li の中心線の、「0 行目の行送りの箱の始端+pitch/2」からの距離(追加が無ければ pitch × li)
bool complete
本文を最後まで組めた
std::vector< StyleMetrics > styleMetrics
styles と同じ添字(第一候補フォントから)
std::vector< LineBox > lines
std::vector< TextStyle > styles
PlacedGlyph::styleIndex → スタイル
float rotation
段落の回転(度。emitParagraph が Group で包む)
size_t charStart
組んだ範囲(UTF-16)
Pt blockExtent() const
全行が占める行送り方向の量
std::u16string text() const
void addImage(std::shared_ptr< const dl::Image > image, Size size, TextStyle style)
行内画像を足す(本文中の位置は U+FFFC 1 文字ぶん)
Definition paragraph.hpp:73
void addObject(std::string handler, std::u16string source, std::map< std::string, std::string > params, TextStyle style)
外部ハンドラのオブジェクト(数式など)を行内に足す。style は周囲の本文(サイズの基準・ベースライン)
Definition paragraph.hpp:98
void addPlaceholder(Size size, TextStyle style, std::string id=std::string())
行内プレースホルダ(大きさだけの空箱)を足す。本文中の位置は U+FFFC 1 文字ぶん。描かれないので、 組んだあと placeholderRects() / charBoxes() で位置を取り、ホ...
Definition paragraph.hpp:87
ParagraphStyle style
Definition paragraph.hpp:59
void addFootnote(Paragraph note, TextStyle markerStyle)
脚注を足す。本文のこの位置に記号(番号。markerStyle は上付きにしておく: superscriptStyle)が入り、 注の本文 note は FlowLayouter がその行の載る段の末尾...
std::vector< InlineRun > runs
Definition paragraph.hpp:57
std::vector< Annotation > annotations
範囲は段落全体の UTF-16 位置
Definition paragraph.hpp:58
void addObject(std::shared_ptr< const obj::ObjectResult > object, TextStyle style)
解決済みのオブジェクトを行内に足す
const TextStyle & baseStyle() const
本文スタイル(先頭の run。無ければ既定)
static Paragraph plain(std::u16string text, TextStyle style, ParagraphStyle pstyle={})
Definition paragraph.hpp:65
プレースホルダの位置(id と物理矩形)。id 未指定のものは ""
スタイルごとの、描くときに要るメトリクス(ParagraphFragment::styleMetrics。styles と同じ添字)
Pt baseline
中心線からベースラインへ(横組み。block 軸で下が正)
font::DecorationMetrics decoration
下線・打消し線の位置と太さ
1 行計測(折り返さない)
Pt descent
反対側。正
Pt ascent
中心線から注記側の張り出し(横組み: 上)。正
size_t clusterCount
クラスタ(文字)数
Pt advance
送り方向の長さ(字間・約物の詰めは入らない: ベタ組みの送りの和)