diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-11 17:31:00 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-11 17:31:00 +0300 |
commit | aea927e6932fd2ef415b1f592d1c7a137ee0511f (patch) | |
tree | 1363ea3add308c8f5750d294150e99ed49e0b7e0 | |
parent | f7b06f4151a732a3b60f52aed1d51ce8460f1fe7 (diff) |
GmDocument: Big lede is all or nothing
Font size should not suddenly change halfway through a paragraph.
-rw-r--r-- | src/gmdocument.c | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index f0c8f2b7..f6db8a1d 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -370,7 +370,7 @@ static void updateOpenURLs_GmDocument_(iGmDocument *d) { | |||
370 | iDeclareType(RunTypesetter) | 370 | iDeclareType(RunTypesetter) |
371 | 371 | ||
372 | struct Impl_RunTypesetter { | 372 | struct Impl_RunTypesetter { |
373 | iGmDocument *doc; | 373 | iArray layout; |
374 | iGmRun run; | 374 | iGmRun run; |
375 | iInt2 pos; | 375 | iInt2 pos; |
376 | float lineHeightReduction; | 376 | float lineHeightReduction; |
@@ -379,10 +379,29 @@ struct Impl_RunTypesetter { | |||
379 | int rightMargin; | 379 | int rightMargin; |
380 | iBool isWordWrapped; | 380 | iBool isWordWrapped; |
381 | iBool isPreformat; | 381 | iBool isPreformat; |
382 | int bigCount; | ||
383 | const int *fonts; | 382 | const int *fonts; |
384 | }; | 383 | }; |
385 | 384 | ||
385 | static void init_RunTypesetter_(iRunTypesetter *d) { | ||
386 | iZap(*d); | ||
387 | init_Array(&d->layout, sizeof(iGmRun)); | ||
388 | } | ||
389 | |||
390 | static void deinit_RunTypesetter_(iRunTypesetter *d) { | ||
391 | deinit_Array(&d->layout); | ||
392 | } | ||
393 | |||
394 | static void clear_RunTypesetter_(iRunTypesetter *d) { | ||
395 | clear_Array(&d->layout); | ||
396 | } | ||
397 | |||
398 | static void commit_RunTypesetter_(iRunTypesetter *d, iGmDocument *doc) { | ||
399 | pushBackN_Array(&doc->layout, constData_Array(&d->layout), size_Array(&d->layout)); | ||
400 | clear_RunTypesetter_(d); | ||
401 | } | ||
402 | |||
403 | static const int maxLedeLines_ = 10; | ||
404 | |||
386 | static const int colors[max_GmLineType] = { | 405 | static const int colors[max_GmLineType] = { |
387 | tmParagraph_ColorId, | 406 | tmParagraph_ColorId, |
388 | tmParagraph_ColorId, | 407 | tmParagraph_ColorId, |
@@ -408,7 +427,7 @@ static iBool typesetOneLine_RunTypesetter_(iWrapText *wrap, iRangecc wrapRange, | |||
408 | d->run.bounds.size.y = dims.y; | 427 | d->run.bounds.size.y = dims.y; |
409 | d->run.visBounds = d->run.bounds; | 428 | d->run.visBounds = d->run.bounds; |
410 | d->run.visBounds.size.x = dims.x; | 429 | d->run.visBounds.size.x = dims.x; |
411 | pushBack_Array(&d->doc->layout, &d->run); | 430 | pushBack_Array(&d->layout, &d->run); |
412 | d->run.flags &= ~startOfLine_GmRunFlag; | 431 | d->run.flags &= ~startOfLine_GmRunFlag; |
413 | // runLine.start = contPos; | 432 | // runLine.start = contPos; |
414 | // trimStart_Rangecc(&runLine); | 433 | // trimStart_Rangecc(&runLine); |
@@ -744,11 +763,13 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
744 | run.color = colors[text_GmLineType]; | 763 | run.color = colors[text_GmLineType]; |
745 | } | 764 | } |
746 | /* Special formatting for the first paragraph (e.g., subtitle, introduction, or lede). */ | 765 | /* Special formatting for the first paragraph (e.g., subtitle, introduction, or lede). */ |
747 | int bigCount = 0; | 766 | // int bigCount = 0; |
767 | iBool isLedeParagraph = iFalse; | ||
748 | if (type == text_GmLineType && isFirstText) { | 768 | if (type == text_GmLineType && isFirstText) { |
749 | if (!isMono) run.font = firstParagraph_FontId; | 769 | if (!isMono) run.font = firstParagraph_FontId; |
750 | run.color = tmFirstParagraph_ColorId; | 770 | run.color = tmFirstParagraph_ColorId; |
751 | bigCount = 15; /* max lines -- what if the whole document is one paragraph? */ | 771 | // bigCount = 15; /* max lines -- what if the whole document is one paragraph? */ |
772 | isLedeParagraph = iTrue; | ||
752 | isFirstText = iFalse; | 773 | isFirstText = iFalse; |
753 | } | 774 | } |
754 | else if (type != heading1_GmLineType) { | 775 | else if (type != heading1_GmLineType) { |
@@ -793,29 +814,40 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
793 | } | 814 | } |
794 | } | 815 | } |
795 | iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ | 816 | iAssert(!isEmpty_Range(&runLine)); /* must have something at this point */ |
796 | iRunTypesetter rts = { .doc = d, | 817 | /* Typeset the paragraph. */ { |
797 | .run = run, | 818 | iRunTypesetter rts; |
798 | .pos = pos, | 819 | init_RunTypesetter_(&rts); |
799 | .lineHeightReduction = lineHeightReduction, | 820 | rts.run = run; |
800 | .indent = indent * gap_Text, | 821 | rts.pos = pos; |
801 | .layoutWidth = d->size.x, | 822 | rts.lineHeightReduction = lineHeightReduction; |
802 | .rightMargin = rightMargin * gap_Text, | 823 | rts.layoutWidth = d->size.x; |
803 | .isWordWrapped = isWordWrapped, | 824 | rts.indent = indent * gap_Text; |
804 | .isPreformat = isPreformat, | 825 | rts.rightMargin = rightMargin * gap_Text; |
805 | .bigCount = bigCount, | 826 | rts.isWordWrapped = isWordWrapped; |
806 | .fonts = fonts }; | 827 | rts.isPreformat = isPreformat; |
807 | // while (!isEmpty_Range(&runLine)) { | 828 | rts.fonts = fonts; |
808 | // runLine = typesetOneLine_RunTypesetter_(&rts, runLine); | 829 | iWrapText wrapText = { .text = runLine, |
809 | // } | 830 | .maxWidth = isWordWrapped ? d->size.x - run.bounds.pos.x - |
810 | iWrapText wrapText = { .text = runLine, | 831 | rts.indent - rts.rightMargin |
811 | .maxWidth = isWordWrapped ? d->size.x - run.bounds.pos.x - | 832 | : 0 /* unlimited */, |
812 | rts.indent - rts.rightMargin | 833 | .mode = word_WrapTextMode, |
813 | : 0 /* unlimited */, | 834 | .wrapFunc = typesetOneLine_RunTypesetter_, |
814 | .mode = word_WrapTextMode, | 835 | .context = &rts }; |
815 | .wrapFunc = typesetOneLine_RunTypesetter_, | 836 | for (;;) { /* may need to retry */ |
816 | .context = &rts }; | 837 | measure_WrapText(&wrapText, run.font); |
817 | measure_WrapText(&wrapText, run.font); | 838 | if (!isLedeParagraph || size_Array(&rts.layout) <= maxLedeLines_) { |
818 | pos = rts.pos; | 839 | commit_RunTypesetter_(&rts, d); |
840 | break; | ||
841 | } | ||
842 | clear_RunTypesetter_(&rts); | ||
843 | rts.pos = pos; | ||
844 | rts.run.font = rts.fonts[text_GmLineType]; | ||
845 | rts.run.color = colors [text_GmLineType]; | ||
846 | isLedeParagraph = iFalse; | ||
847 | } | ||
848 | pos = rts.pos; | ||
849 | deinit_RunTypesetter_(&rts); | ||
850 | } | ||
819 | /* Flag the end of line, too. */ | 851 | /* Flag the end of line, too. */ |
820 | ((iGmRun *) back_Array(&d->layout))->flags |= endOfLine_GmRunFlag; | 852 | ((iGmRun *) back_Array(&d->layout))->flags |= endOfLine_GmRunFlag; |
821 | /* Image or audio content. */ | 853 | /* Image or audio content. */ |