Devanagari text rendering improperly in PyGame

2019-04-19 05:33发布

问题:

We have a small web app that we want to convert into something native. Right now, it's got a lot of moving parts (the backend, the browser etc.) and we'd like to convert it into a single tight application. We decided to use PyGame to do this and it's been fine so far except for a font rendering issue.

The string I'd like to render is कोझिकोड. This, correctly rendered looks like .

The specific code points are \u0915 \u094b \u091d \u093f \u0915 \u094b and \u0921

Now, this looks fine in my editor and my browser but when I try to render it in PyGame, I get this . Basically, the vowel sign (\u093f ि) should have been on the left of the झ but it appears to its right (and to the left of the क) thereby messing it up completely. This doesn't happen in a browser or a text editor (with the same input string) so I'm guessing it a renderer problem in PyGame.

There is one crude fix which works only in this specific case which i s to put the ि (\u093f) before the झ (\u091d). In that case, it renders properly like so . This relies on me knowing something about the language and putting that logic into the code. I have to deal with multiple languages here so that's not really feasible.

I don't have much experience with unicode so I don't know how to approach this problem. Is there something I can do to fix this?

In case it matters, I'm using the freesans font which is there on Debian and which has the necessary glyphs to render this.

Update: The code to actually render this is as follows

# -*- coding: utf-8 -*-
import time

import pygame

# Pygame setup and create root window
pygame.font.init()
screen = pygame.display.set_mode((320, 200))
empty = pygame.Surface((320, 200))


font_file = pygame.font.match_font("freesans")  # Select and
font = pygame.font.Font(font_file, 30)          # open the font
writing = font.render(u"कोिझकोड  कोझिकोड", True, (0, 0, 0))  # Render text on a surface
screen.fill((255, 255, 255)) # Clear the background
screen.blit(writing, (10, 10)) # Blit the text surface on the background
pygame.display.flip()  # Refresh the display

input() # Wait for input before quitting

This is what it looks like

The first word is rendered correctly but we've done it by inverting the vowel and the letter positions as I mentioned in the crude fix. The second is written properly but not rendered correctly.

Update 2: In the absence of anything else, I've decided to try to render the string into an image using an external program and then blit this image onto the PyGame Surface. I tried imagemagick but it messes us in the same way as this. Gimp works fine and so I'm planning to use the batch mode to get my work done.

回答1:

I think is a SDL_ttf problem (the underlying component which actually renders the text).

While my IDE correctly renders the string

The SDL_TTF program does not:

There is the code: https://gist.github.com/ilario-pierbattista/be6b967b05fa2f1eb322f35988a33ad0

I'm still looking for a solution



回答2:

I had to finally resort to a really ugly but usable workaround for my own situation. I wrote a script-fu plugin which takes a filename and a piece of text as arguments. It then writes out the text and saves it a png file using gimp. My program then loads this up and blits the png directly onto the surface.