A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: image centering bleed (#1096)

## Summary

* Fixes #1026
* Added a reproducer chapter to the epub generator for this case
* The fix is in endElement — when leaving a block/header element that
had an empty text block, reset the alignment to the user's default so it
doesn't bleed into the next sibling. This preserves accumulated margins
from parent elements while preventing stale alignment from carrying
across.

## Additional Context

### Before fix


![20260222_210029262](https://github.com/user-attachments/assets/263e4608-18cf-418b-871a-1c9a71822bdf)

![20260222_210040995](https://github.com/user-attachments/assets/9f0fdea1-5abf-4f1c-b35d-d35c8309456a)

![20260222_210052640](https://github.com/user-attachments/assets/b77dbadc-f347-400b-994a-17d0f5f073d8)

### After fix


![20260222_211037007](https://github.com/user-attachments/assets/294e15b3-ee40-4c21-8f5b-bd6b40d43d8d)

![20260222_211045139](https://github.com/user-attachments/assets/74107cf9-08a2-4737-be7f-ed0b5648ca6f)

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**< PARTIALLY **_

authored by

martin brook and committed by
GitHub
f8a9f1f0 052f497b

+36
+14
lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
··· 789 789 if (headerOrBlockTag) { 790 790 self->currentCssStyle.reset(); 791 791 self->updateEffectiveInlineStyle(); 792 + 793 + // Reset alignment on empty text blocks to prevent stale alignment from bleeding 794 + // into the next sibling element. This fixes issue #1026 where an empty <h1> (default 795 + // Center) followed by an image-only <p> causes Center to persist through the chain 796 + // of empty block reuse into subsequent text paragraphs. 797 + // Margins/padding are preserved so parent element spacing still accumulates correctly. 798 + if (self->currentTextBlock && self->currentTextBlock->isEmpty()) { 799 + auto style = self->currentTextBlock->getBlockStyle(); 800 + style.textAlignDefined = false; 801 + style.alignment = (self->paragraphAlignment == static_cast<uint8_t>(CssTextAlign::None)) 802 + ? CssTextAlign::Justify 803 + : static_cast<CssTextAlign>(self->paragraphAlignment); 804 + self->currentTextBlock->setBlockStyle(style); 805 + } 792 806 } 793 807 } 794 808
+22
scripts/generate_test_epub.py
··· 607 607 <img src="images/cache_test_2.jpg" alt="Cache test 2"/> 608 608 <p>Navigate back to Page A - it should load faster from cache.</p> 609 609 """), [('cache_test_2.jpg', images['cache_test_2.jpg'])]), 610 + ("9. Alignment Bleed", make_chapter("Image Centering Bleed Test", """ 611 + <p>Tests that image centering does not bleed into following text blocks (issue #1026).</p> 612 + <p>Set Paragraph Alignment to Justify and Embedded Style to OFF before testing.</p> 613 + <p>All paragraphs below the images should be justified, not centered.</p> 614 + <h1 class="hidden"></h1> 615 + <p><img src="images/centering_test.jpg" alt="Test image"/></p> 616 + <div> 617 + <p>FIRST PARAGRAPH after image. This paragraph follows an empty heading and an image-only paragraph. With the bug present, this text appears centered instead of justified because the empty heading's default Center alignment bleeds through the chain of empty text blocks. Lorem ipsum dolor sit amet, consectetur adipiscing elit sed do eiusmod tempor.</p> 618 + <p>SECOND PARAGRAPH in the same div. This paragraph should always be justified because the first paragraph's text block was flushed. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia.</p> 619 + </div> 620 + """), []), # centering_test.jpg already included by chapter 4 610 621 ] 611 622 612 623 create_epub(OUTPUT_DIR / 'test_jpeg_images.epub', 'JPEG Image Tests', jpeg_chapters) ··· 661 672 <img src="images/cache_test_2.png" alt="Cache test 2"/> 662 673 <p>Navigate back to Page A - it should load faster from cache.</p> 663 674 """), [('cache_test_2.png', images['cache_test_2.png'])]), 675 + ("9. Alignment Bleed", make_chapter("Image Centering Bleed Test", """ 676 + <p>Tests that image centering does not bleed into following text blocks (issue #1026).</p> 677 + <p>Set Paragraph Alignment to Justify and Embedded Style to OFF before testing.</p> 678 + <p>All paragraphs below the images should be justified, not centered.</p> 679 + <h1 class="hidden"></h1> 680 + <p><img src="images/centering_test.png" alt="Test image"/></p> 681 + <div> 682 + <p>FIRST PARAGRAPH after image. This paragraph follows an empty heading and an image-only paragraph. With the bug present, this text appears centered instead of justified because the empty heading's default Center alignment bleeds through the chain of empty text blocks. Lorem ipsum dolor sit amet, consectetur adipiscing elit sed do eiusmod tempor.</p> 683 + <p>SECOND PARAGRAPH in the same div. This paragraph should always be justified because the first paragraph's text block was flushed. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident sunt in culpa qui officia.</p> 684 + </div> 685 + """), []), # centering_test.png already included by chapter 4 664 686 ] 665 687 666 688 create_epub(OUTPUT_DIR / 'test_png_images.epub', 'PNG Image Tests', png_chapters)
test/epubs/test_jpeg_images.epub

This is a binary file and will not be displayed.

test/epubs/test_png_images.epub

This is a binary file and will not be displayed.