diff options
Diffstat (limited to 'src/gmdocument.c')
-rw-r--r-- | src/gmdocument.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c index c3f0005c..f0ffb34c 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -240,12 +240,14 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li | |||
240 | int len = 0; | 240 | int len = 0; |
241 | if ((len = decodeBytes_MultibyteChar(desc.start, size_Range(&desc), &icon)) > 0) { | 241 | if ((len = decodeBytes_MultibyteChar(desc.start, size_Range(&desc), &icon)) > 0) { |
242 | if (desc.start + len < desc.end && | 242 | if (desc.start + len < desc.end && |
243 | (isPictograph_Char(icon) || isEmoji_Char(icon)) && | 243 | (isPictograph_Char(icon) || isEmoji_Char(icon) || icon == 0x2022 /* bullet */) && |
244 | !isFitzpatrickType_Char(icon)) { | 244 | !isFitzpatrickType_Char(icon)) { |
245 | link->flags |= iconFromLabel_GmLinkFlag; | 245 | link->flags |= iconFromLabel_GmLinkFlag; |
246 | link->labelIcon = (iRangecc){ desc.start, desc.start + len }; | 246 | link->labelIcon = (iRangecc){ desc.start, desc.start + len }; |
247 | line.start += len; | 247 | line.start += len; |
248 | line.start = skipSpace_CStr(line.start); | 248 | line.start = skipSpace_CStr(line.start); |
249 | // printf("custom icon: %x (%s)\n", icon, cstr_Rangecc(link->labelIcon)); | ||
250 | // fflush(stdout); | ||
249 | } | 251 | } |
250 | } | 252 | } |
251 | } | 253 | } |
@@ -301,6 +303,27 @@ static enum iGmDocumentTheme currentTheme_(void) { | |||
301 | : prefs_App()->docThemeLight); | 303 | : prefs_App()->docThemeLight); |
302 | } | 304 | } |
303 | 305 | ||
306 | static void alignDecoration_GmRun_(iGmRun *run, iBool isCentered) { | ||
307 | const iRect visBounds = visualBounds_Text(run->font, run->text); | ||
308 | const int visWidth = width_Rect(visBounds); | ||
309 | if (!isCentered) { | ||
310 | /* Keep the icon aligned to the left edge. */ | ||
311 | run->visBounds.pos.x -= left_Rect(visBounds); | ||
312 | if (visWidth > width_Rect(run->visBounds)) { | ||
313 | /* ...unless it's a wide icon, in which case move it to the left. */ | ||
314 | run->visBounds.pos.x -= visWidth - width_Rect(run->visBounds); | ||
315 | } | ||
316 | else if (visWidth < width_Rect(run->visBounds) * 3 / 4) { | ||
317 | /* ...or a narrow icon, which needs to be centered but leave a gap. */ | ||
318 | run->visBounds.pos.x += (width_Rect(run->visBounds) * 3 / 4 - visWidth) / 2; | ||
319 | } | ||
320 | } | ||
321 | else { | ||
322 | /* Centered. */ | ||
323 | run->visBounds.pos.x += (width_Rect(run->visBounds) - visWidth) / 2; | ||
324 | } | ||
325 | } | ||
326 | |||
304 | static void doLayout_GmDocument_(iGmDocument *d) { | 327 | static void doLayout_GmDocument_(iGmDocument *d) { |
305 | const iBool isMono = isForcedMonospace_GmDocument_(d); | 328 | const iBool isMono = isForcedMonospace_GmDocument_(d); |
306 | const iBool isNarrow = d->size.x < 90 * gap_Text; | 329 | const iBool isNarrow = d->size.x < 90 * gap_Text; |
@@ -510,12 +533,15 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
510 | /* TODO: Literata bullet is broken? */ | 533 | /* TODO: Literata bullet is broken? */ |
511 | iGmRun bulRun = run; | 534 | iGmRun bulRun = run; |
512 | bulRun.color = tmQuote_ColorId; | 535 | bulRun.color = tmQuote_ColorId; |
513 | bulRun.visBounds.pos = addX_I2(pos, indent * gap_Text); | 536 | bulRun.visBounds.pos = addX_I2(pos, (indents[text_GmLineType] - 0.55f) * gap_Text); |
514 | bulRun.visBounds.size = advance_Text(run.font, bullet); | 537 | bulRun.visBounds.size = |
515 | bulRun.visBounds.pos.x -= 4 * gap_Text - width_Rect(bulRun.visBounds) / 2; | 538 | init_I2((indents[bullet_GmLineType] - indents[text_GmLineType]) * gap_Text, |
539 | lineHeight_Text(bulRun.font)); | ||
540 | // bulRun.visBounds.pos.x -= 4 * gap_Text - width_Rect(bulRun.visBounds) / 2; | ||
516 | bulRun.bounds = zero_Rect(); /* just visual */ | 541 | bulRun.bounds = zero_Rect(); /* just visual */ |
517 | bulRun.text = range_CStr(bullet); | 542 | bulRun.text = range_CStr(bullet); |
518 | bulRun.flags |= decoration_GmRunFlag; | 543 | bulRun.flags |= decoration_GmRunFlag; |
544 | alignDecoration_GmRun_(&bulRun, iTrue); | ||
519 | pushBack_Array(&d->layout, &bulRun); | 545 | pushBack_Array(&d->layout, &bulRun); |
520 | } | 546 | } |
521 | /* Quote icon. */ | 547 | /* Quote icon. */ |
@@ -555,8 +581,13 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
555 | if (!isEmpty_Range(&link->labelIcon)) { | 581 | if (!isEmpty_Range(&link->labelIcon)) { |
556 | icon.text = link->labelIcon; | 582 | icon.text = link->labelIcon; |
557 | } | 583 | } |
558 | icon.font = regular_FontId; | 584 | /* TODO: List bullets needs the same centering logic. */ |
559 | /* Center the icon within the indentation. */ { | 585 | /* Special exception for the tiny bullet operator. */ |
586 | icon.font = equal_Rangecc(link->labelIcon, "\u2219") ? regularMonospace_FontId | ||
587 | : regular_FontId; | ||
588 | alignDecoration_GmRun_(&icon, iFalse); | ||
589 | #if 0 | ||
590 | { | ||
560 | const iRect visBounds = visualBounds_Text(icon.font, icon.text); | 591 | const iRect visBounds = visualBounds_Text(icon.font, icon.text); |
561 | const int visWidth = width_Rect(visBounds); | 592 | const int visWidth = width_Rect(visBounds); |
562 | /* Keep the icon aligned to the left edge. */ | 593 | /* Keep the icon aligned to the left edge. */ |
@@ -570,6 +601,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
570 | icon.visBounds.pos.x += (width_Rect(icon.visBounds) * 3 / 4 - visWidth) / 2; | 601 | icon.visBounds.pos.x += (width_Rect(icon.visBounds) * 3 / 4 - visWidth) / 2; |
571 | } | 602 | } |
572 | } | 603 | } |
604 | #endif | ||
573 | icon.color = linkColor_GmDocument(d, run.linkId, icon_GmLinkPart); | 605 | icon.color = linkColor_GmDocument(d, run.linkId, icon_GmLinkPart); |
574 | icon.flags |= decoration_GmRunFlag; | 606 | icon.flags |= decoration_GmRunFlag; |
575 | pushBack_Array(&d->layout, &icon); | 607 | pushBack_Array(&d->layout, &icon); |