镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

RTL Direction not having any effect #4511

Closed

Description

@CovertError

What did you do?

I'm trying to put text on top of an image and I also set the direction to RTL when doing this before I used to get some library not installed called libraqm but no with it install it still doesn't work I'm testing with the Arabic language

What did you expect to happen?

the text goes RTL

What actually happened?

the text went LTR

What are your OS, Python and Pillow versions?

  • OS: Ubuntu 18
  • Python: 3.6
  • Pillow: latest version
def PhotoAlterer(name):
    image = Image.open('check.jpeg')

    draw = ImageDraw.Draw(image)

    font = ImageFont.truetype('din-next-lt-w23-medium.ttf', size=60)

    text_to_be_reshaped = '%s' % name
    reshaped_text = arabic_reshaper.reshape(text_to_be_reshaped)
    (x, y) = (1050, 427)
    color = 'rgb(255, 255, 255)'  # white color
    draw.text((x, y), reshaped_text , fill=color, font=font, direction="rtl")

    image.save('pImg/%s.png' % name)

Activity

  1. radarhere commented on Apr 2, 2020

    @radarhere
    Member

    Could you adjust the code that you've provided so that it's self-contained? At the moment, I don't know the value of name or what arabic_reshaper does.

  2. radarhere commented on Apr 10, 2020

    @radarhere
    Member

    This is the sequel to #4496

    So from that, it seems reasonable to presume that arabic_reshaper is https://pypi.org/project/arabic-reshaper/, and that 'محمد' is a valid value for text_to_be_reshaped.

    from PIL import Image, ImageDraw, ImageFont
    import arabic_reshaper
    
    def PhotoAlterer(name):
        image = Image.open('check.jpeg')
    
        draw = ImageDraw.Draw(image)
    
        font = ImageFont.truetype('din-next-lt-w23-medium.ttf', size=60)
    
        text_to_be_reshaped = '%s' % name
        reshaped_text = arabic_reshaper.reshape(text_to_be_reshaped)
        (x, y) = (1050, 427)
        color = 'rgb(255, 255, 255)'  # white color
        draw.text((x, y), reshaped_text , fill=color, font=font, direction="rtl")
    
        image.save('pImg/%s.png' % name)
    
    PhotoAlterer('محمد')

    You may be interested in #3081 (comment), but more likely, you're looking for #3125 (comment)

    The direction parameter sets the overall paragraph direction, the individual character's direction is determined by BiDi algorithm. Unicode bidi control characters can be to force text direction to be LTR or RTL and override the algorithm (though that is not usually something very useful todo, expect for ancient scripts that can be written in either direction or pseudo RTL localization strings).

  3. CovertError commented on Apr 13, 2020

    @CovertError
    Author

    yes I have tried that library but the same thing still happens the text just keeps going LTR my temp solution to this is to find the size of the message and subtract it for the x coordinates like so

    gettingTextSize = draw.textsize(reshaped_text, font=font)
    spaceToAdd = gettingTextSize.__getitem__(0)
    width = 1050 - (spaceToAdd)
  4. CovertError commented on Apr 13, 2020

    @CovertError
    Author

    Could you adjust the code that you've provided so that it's self-contained? At the moment, I don't know the value of name or what arabic_reshaper does.

    arabic_reshaper is really helpful if fixes the Arabic language with python somehow without it Arabic letters wouldn't be attached together so let's say "محمد" this is how it should look like and it's just the name Mohammed but in Arabic, so without the arabic_reshaper it would look like "م ح م د" I had to use spaces to emulate it but essentially the letters would be separated

    maybe a good it's good to just shift to using arabic_reshaper instead of libraqm I'm really sure what are you using it for but it's just easier to work with other libraries like arabic_reshaper

  5. nulano commented on Apr 13, 2020

    @nulano
    Contributor

    I have opened Ubuntu 18.04 live in VirtualBox with a full Pillow install from master with raqm following the Installation documentation to test this. I ran the following commands in a Python console:

    from PIL import Image, ImageDraw, ImageFont
    import arabic_reshaper
    from bidi.algorithm import get_display as bidi_get_display
    im = Image.new("RGB", (400, 400), "white")
    d = ImageDraw.Draw(im)
    text = "\u0645\u062D\u0645\u062F"   # محمد in unicode code points
    reshaped = arabic_reshaper.reshape(text)
    reshaped.encode("unicode-escape")    # prints b'\\ufee3\\ufea4\\ufee4\\ufeaa'
    bidi = bidi_get_display(reshaped)
    bidi.encode("unicode-escape")    # prints b'\\ufeaa\\ufee4\\ufea4\\ufee3'
    
    # test without libraqm
    fb = ImageFont.truetype("KacstBook.ttf", 60, layout_engine=ImageFont.LAYOUT_BASIC)
    d.text((0,   0), text, "black", font=fb)    # shows م l ح l م l د (l added to stop browser shaping)
    d.text((0, 100), text, "black", font=fb, direction='ltr')    # fails as expected
    d.text((0, 200), text, "black", font=fb, direction='rtl')    # fails as expected
    d.text((100,   0), reshaped, "black", font=fb)    # shows محمد, but reversed
    d.text((100, 100), reshaped, "black", font=fb, direction='ltr')    # fails as expected
    d.text((100, 200), reshaped, "black", font=fb, direction='rtl')    # fails as expected
    d.text((0, 300), bidi, "black", font=fb)    # shows محمد correctly
    
    # test with libraqm
    fr = ImageFont.truetype("KacstBook.ttf", 60, layout_engine=ImageFont.LAYOUT_RAQM)
    d.text((200,   0), text, "black", font=fr)    # shows محمد correctly
    d.text((200, 100), text, "black", font=fr, direction='ltr')    # shows محمد
    d.text((200, 200), text, "black", font=fr, direction='rtl')    # shows محمد
    d.text((300,   0), reshaped, "black", font=fr)    # shows محمد correctly
    d.text((300, 100), reshaped, "black", font=fr, direction='ltr')    # shows محمد
    d.text((300, 200), reshaped, "black", font=fr, direction='rtl')    # shows محمد
    d.text((300, 300), bidi, "black", font=fb)    # shows محمد, but reversed
    
    im.save("a.png")

    As you can see, you can either use libraqm to handle text shaping (in which case arabic_reshaper has no effect and python_bidi causes a conflict), or you can use arabic_reshaper+python_bidi with the basic layout in Pillow (the 'legacy' option).

    The direction parameter has no effect on arabic, as it only affects the direction of symbols (e.g. a comma, plus, minus, ...) as @radarhere quoted in the comment above. See also #3125 (comment) from the same discussion:

    With regards to 2 in the original post, I don't think this is how rtl works. English characters are strong characters, and have a definite directionality. However, weak characters, such as arithmetical symbols, do not and are able to be shown right-to-left by Pillow.

  6. nulano commented on Apr 13, 2020

    @nulano
    Contributor

    yes I have tried that library but the same thing still happens the text just keeps going LTR my temp solution to this is to find the size of the message and subtract it for the x coordinates like so

    gettingTextSize = draw.textsize(reshaped_text, font=font)
    spaceToAdd = gettingTextSize.__getitem__(0)
    width = 1050 - (spaceToAdd)
    

    Oh, I think I see the problem now. The xy parameter always specifies the top-left point of the text. The direction parameter is not used to make text appear to the left of this point, but as a hint to the shaping algorithm used by libraqm. If you wish to have text appear to the left of this point, you have to use the steps such as in your comment.

    # using libraqm
    fr = ImageFont.truetype("KacstBook.ttf", 60, layout_engine=ImageFont.LAYOUT_RAQM)
    text = "\u0645\u062D\u0645\u062F"   # محمد in unicode code points
    x, y = (1050, 427)
    w, h = d.textsize(text, font=fr)
    d.text((x-w, y), text, "black", font=fr)
    
    # using arabic_reshaper + python_bidi
    fb = ImageFont.truetype("KacstBook.ttf", 60, layout_engine=ImageFont.LAYOUT_BASIC)
    text = "\u0645\u062D\u0645\u062F"   # محمد in unicode code points
    reshaped = arabic_reshaper.reshape(text)
    bidi_text = bidi.algorithm.get_display(reshaped)
    x, y = (1050, 427)
    w, h = d.textsize(bidi_text, font=fb)
    d.text((x-w, y), text, "black", font=fb)
    

    To see what the direction parameter actually does, pass it undirected text, such as "+-=" (as mentioned in my previous comment):

    font = ImageFont.truetype("DejaVuSans.ttf", 60, layout_engine=ImageFont.LAYOUT_RAQM)
    draw.text((0, 0), "+-=", "black", font=font, direction="ltr")    # shows +-=
    draw.text((0, 100), "+-=", "black", font=font, direction="rtl")    # shows =-+
    
  7. nulano commented on Apr 13, 2020

    @nulano
    Contributor

    If you wish to have text appear to the left of this point, you have to use the steps such as in your comment.

    Looking at the docs, it looks like there is an undocumented parameter anchor=None that might be intended for this. Looking through the history, this has been present since the PIL fork, but never implemented, and always ignored. The only other mention I can find is in #285 ("might be implemented in the future"). #1660 seems to have attempted to do this in a different way, but was not accepted. I'll try to make a PR for this using the anchor parameter later today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions