summaryrefslogtreecommitdiff
path: root/src/gmdocument.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-07-11 17:31:00 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-07-11 17:31:00 +0300
commitaea927e6932fd2ef415b1f592d1c7a137ee0511f (patch)
tree1363ea3add308c8f5750d294150e99ed49e0b7e0 /src/gmdocument.c
parentf7b06f4151a732a3b60f52aed1d51ce8460f1fe7 (diff)
GmDocument: Big lede is all or nothing
Font size should not suddenly change halfway through a paragraph.
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r--src/gmdocument.c88
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) {
370iDeclareType(RunTypesetter) 370iDeclareType(RunTypesetter)
371 371
372struct Impl_RunTypesetter { 372struct 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
385static void init_RunTypesetter_(iRunTypesetter *d) {
386 iZap(*d);
387 init_Array(&d->layout, sizeof(iGmRun));
388}
389
390static void deinit_RunTypesetter_(iRunTypesetter *d) {
391 deinit_Array(&d->layout);
392}
393
394static void clear_RunTypesetter_(iRunTypesetter *d) {
395 clear_Array(&d->layout);
396}
397
398static 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
403static const int maxLedeLines_ = 10;
404
386static const int colors[max_GmLineType] = { 405static 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. */