txoof / epdlib

Python library for creating and writing modular layouts for e-paper screens
GNU General Public License v3.0
16 stars 8 forks source link

Right Aligned text should align with right side of TextBlock #65

Closed tristanhaeuser closed 5 months ago

tristanhaeuser commented 6 months ago

I'm working on a Waveshare 6'' HD EPD with IT8951 controller. When attempting to set up a right-aligned text within a text block I encounter unexpected spacing from the right border. Despite setting no padding and experimenting with various available properties, the issue persists. Additionally, I've noticed that even with left-aligned text, there's an invisible padding that restricts the utilization of the entire screen. This padding is problematic as it prevents optimal use of the display area. Is this expected behaviour to have a safety margin on the right side or a bug somewhere in the library?

IMG_4188

Section = {
    'text': {
        'type': 'TextBlock',
        'max_lines': 25,
        'align': 'right',
        'padding': 0,
        'width': 1,
        'height': 1,
        'abs_coordinates': (0, 0),
        'hcenter': False,
        'vcenter': True,
        'relative': None,
        'font': sf_font,
        'font_size': None,
        'inverse': False,
        'text_wrap': True,
        'fill': 'White',
        'bkground': 'Black',
        'mode': 'L'
    }
}
txoof commented 6 months ago

You've probably found a bug. That definitely doesn't look right. Thanks for providing the layout and font.

Let me take a poke at this and see if there's something I can do to fix it.

Would you mind sharing an image for the left-aligned issue as well.

Just to be certain, is the resolution of your screen 1448 X 1072?

tristanhaeuser commented 6 months ago

Yes, that's correct the resolution is 1448 x 1072. Here is an image for the left-aligned issue:

IMG_4191

I think the bug is not font-specific. I used a variety of fonts while developing and it doesn't seem like it would make any difference.

txoof commented 6 months ago

I've tracked down what's causing this problem.

The root cause is that the text-wrapping algorithm is relatively conservative as to how it goes about splitting up text. Because of this the calculations for determining characters per line is also relatively conservative. When a TextBlock object is born, it looks at it's ratio, calculates out its internal resolution, works out any padding needed and then does a bunch of calculations to "guess" how many characters can fit on a line based on the supplied font and the character distribution for the supplied language. It looks like the vertical calculations are too conservative.

I'm not sure what font you're using, but when I test this using OpenSans-Regular, at 1072x1448, I get 44 characters per line. You can override this and get better (read "different") results. Try the code snip below. I'm working in Jupyter Lab so it's fairly easy to test.

l = {
    'text': {
        'type': 'TextBlock',
        'max_lines': 25,
        'align': 'left', # left justified because the math is more correct
        'padding': 0,
        'width': 1,
        'height': 1,
        'abs_coordinates': (0, 0),
        'hcenter': False,
        'vcenter': True,
        'relative': None,
        'font': '../fonts/Open_Sans/OpenSans-Regular.ttf',
        'font_size': None,
        'inverse': False,
        'text_wrap': True,
        'fill': 'White',
        'bkground': 'Black',
        'mode': 'L'
    }
}
text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit...-snipped for brevity'
my_layout = Layout(resolution=(1072, 1448))
tb = my_layout.blocks['text']
tb.maxchar = 100 # try different values between 40 and 100 to see what happens when you over-run the wrap
my_layout.update_contents({'text': text})
my_layout.concat()

maxchar = 44 (calculated "best")

image

maxchar = 55 (note some lines run off screen)

image

maxchar = 100 (note many lines run off screen)

image

The weird border issue you are having with right justified text is a result of this. I clearly got some of the math wrong when handling right justified text; the "useless" space should appear on the left side of right justified text.

txoof commented 6 months ago

@tristanhaeuser I'll see if I can fix the justification issue and at least get right justification to shove over to the right side and leave "useless" space on the left instead.

As for distributing text better, I'm open to suggestions. I really struggled to get a solution that worked well for most TextBlock sizes. The calculations happen in Block.TextBlock. If you have any ideas how to make this a bit better, I'd love to have some other brains working on it.

Ideally, it would be a bit more dynamic and flow text with the logic of a soft-wrap, but I haven't really thought much about how to do that. I was focused on using the textwrap library.

txoof commented 6 months ago

looks like TextBlock needs an additional case for right aligned text somewhere around l1087.

It's too late tonight to figure out the math, but this is the gist:

if self.align == 'ralign'
   paste_x = <<insert math here for shoving text to right border>>>
   logging.debug('pasting raligned text on the right side')
txoof commented 6 months ago

@tristanhaeuser I've done some research and I can't find a good alternative to textwrap other than trying to do it from the ground up.

If you have any ideas, I'd love to hear them. I'm going to dig into your right justification bug shortly and hopefully have a solution this weekend.

txoof commented 6 months ago

@tristanhaeuser well, that was easier than I thought!

I've got a fix ready to go, but I'd appreciate it if you could test it out. The output is below.

You can install the issue-branch with:

pip install git+https://github.com/txoof/epdlib/epdlib.git@I65_alignment

image

tristanhaeuser commented 6 months ago

@txoof Wow, thank you for coming up with a fix so quickly. I'm currently very busy, but I try it out as soon as possible. I let you know when I tested it. Should I close this issue?

txoof commented 6 months ago

No problem. I hope this resolves your problem. The fix was earlier than I thought.

Leave it open until you've tested. I'll close it when I merge the update.

tristanhaeuser commented 5 months ago

@txoof I installed the branch with the fix. As far as I can tell everything works now as expected. : )

txoof commented 5 months ago

Thanks for checking. I'll merge it in when I get a minute and publish to PyPi.

Don't forget to update your requirements.txt!

txoof commented 5 months ago

@tristanhaeuser the v0.6.5 is up on pypi. Happy hacking!

If you find any other issues with this, feel free to reopen the ticket.