ReportLab Django Not Rendering Chinese Characters - python

I'm having difficulty making ReportLab render Chinese Characters. From everything I've looked up people are saying that it is probably a font problem but I've used a lot of different fonts and it doesn't even seem to be using them at all. The Chinese characters always just come out as black squares. Below is some sample code of what I have.
# -*- coding: utf8 -*-
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase.ttfonts import TTFont
from io import BytesIO
pdfmetrics.registerFont(TTFont('Arial', 'arial.ttf', 'UTF-8'))
buffer = BytesIO()
doc = SimpleDocTemplate(buffer,
rightMargin=inch*0.5, # 1/2 Inch
leftMargin=inch*0.5, # 1/2 Inch
bottomMargin=0,
topMargin=inch*0.375, # 3/8 Inch
pagesize=letter)
# Get Styles
styles = getSampleStyleSheet()
# Custom Style
styles.add(ParagraphStyle(name='Address', font='Arial', fontSize=8))
elements = []
elements.append(Paragraph(u'6905\u897f\u963f\u79d1\u8857\uff0c\u5927\u53a6\uff03\u5927', styles['Address']))
doc.build(elements)
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
return pdf
I'm using an arial.ttf font found on my Ubuntu 12.04 installation in the fonts folder. I have also tried other fonts installed on this machine and all have exactly the same look even on the numbers and none of the Chinese characters are anything other than black squares.
Am I registering fonts wrong if even the numbers at the beginning aren't printing correctly? What could be causing the black squares?

Solved it. Turns out in your ParagraphStyle it needs to be fontName="Arial" not font="Arial" but I did learn some other tricks of getting it to work in other ways below.
styles.add(ParagraphStyle(name='Address', fontName='Arial')
After doing some digging I've learned a few things that I hope helps someone else in this situation. When you add the tags inside of your Paragraph around the Unicode text and set it explicitly to a font it will work.
elements.append(Paragraph(u'<font name="Arial">6905\u897f\u963f\u79d1\u8857\uff0c\u5927\u53a6\uff03\u5927</font>', styles['Address']))
This fixes the problem at least for Paragraphs with various fonts.
Again this code will work.

Choose the fonts that supports Chinese characters.
In Ubuntu, I choose "AR PL UMing CN" for example.
My code snippets:
# -*- coding: utf-8 -*-
...
pdfmetrics.registerFont(TTFont('AR PL UMing CN', 'uming.ttc'))
styles = getSampleStyleSheet()
...
styles.add(ParagraphStyle(name='Chinese', fontName='AR PL UMing CN', fontSize=20))
elements=[]
elements.append(Paragraph("成”, styles['Chinese']))
doc.build(elements)
...
I can even change to Chinese editor and type in the character straight off. Hope this helps.

Related

MoviePy not displaying non-English characters

I'm trying to display non English characters in movie py but it's not displaying the actual character I typed. The language I'm trying is Telugu. What is the problem in displaying the characters?
This is the code I'm using
# -*- coding: utf-8 -*-
from moviepy.editor import *
# create clip from image
clip = ImageClip('img/1.jpg').on_color((1920, 1080))
clip = clip.set_duration(2)
# add annotation to clip
txtclip = TextClip('n+<ý² yûTq¿£yû', fontsize=50, color='red', font="Deepika")
cvc = CompositeVideoClip([ clip, txtclip.set_pos(('center', 'bottom'))])
cvc = cvc.set_duration(2)
# write video to file
cvc.write_videofile("text.mp4", fps=24)
The characters(Language) displayed in the code is weird but when I copy the text from the original file which was different characters displayed as this. And this worked in displaying the text in PySide QLabel.
Its just displaying boxes instead of the characters.
Can anyone help me with this issue?For your reference I'm adding image of text displayed in the code for language
I had a similar problem. I printed Japanese characters, but they were not displayed in video.
The problem was that the font did not support these characters.
Thus this produced empty result:
my_text = mp.TextClip("すみません。お先に失礼します",
font= "Amiri-regular", color= "white", fontsize= 34)
Solution was to download a custom font and import it as in example:
my_text2 = mp.TextClip("すみません。お先に失礼します",
font="wqy-microhei.ttc", color="white", fontsize=34)
I downloaded this font from github and it can be simply placed into directory with the python source code to be imported.

Telugu (Unicode) font not rendering correctly in pyfpdf

I am trying to render Telugu text into pdf using pyfpdf.
The problem is with font rendition in fpdf.
What might be the problem?
The code I used is :
#!/usr/bin/python
# -*- coding: utf8 -*-
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.add_font('lakkireddy', '', 'LakkiReddy.ttf', uni=True)
pdf.set_font('lakkireddy','', 16)
pdf.cell(40,10,u'హలో ప్రపంచమా!')
pdf.output('testfpdf.pdf','F')`
The expected output is :
But the actual output is broken text :
What could be the issue, Is it the font, Is it encoding or Is it font rendering engine?
Can I define which font rendering engine to use?
I am not familiar with fpdf but it seems that fpdf does not support proper text shaping for complex scripts. Glyph shapes change based on glyph position in the string and based on its neighbor glyphs but fpdf does not seem to do this kind of processing by default.
You have to check if there are options in fpdf for specifying this kind of processing for complex scripts.

Writing Greek in matplotlib labels, titles

I am trying to write some text in Greek for labels, figure title etc. to accompany my plots but so far to no avail.
I don't want to print specific letters (I know how to do this using the special characters notation), I'd rather write the whole text in Greek (probably using Unicode and u'text' ?).
Before receiving suggestions I would like to mention that for some reason I can't get matplotlib to cooperate with TeX (using Ipython notebook from anaconda in Ubuntu 14.10), so that wouldn't really be an option.
I tried loading Arial font and it does load successfully but again I get square blocks instead of characters. I used
import matplotlib.font_manager as fm
prop = fm.FontProperties(fname='/usr/share/fonts/truetype/msttcorefonts/Arial.ttf')
and then for displaying the string I used u'Αποτελέσματα προσομοίωσης'. Arial is supposed to render Greek perfectly and I have used it many times in text editors.
I managed to solve the problem by doing the following:
First, you have to import the necessary libraries and set a font installed on the computer that can for sure render Greek, like the Ubuntu font (Ubuntu Bold in the following code).
import matplotlib.font_manager as fm
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
then you can specifically apply the chosen font to each label, title etc as follows:
plt.title(u"Τίτλος του γραφήματος",fontproperties=fp1)
If that doesn't seem to work, try adding the following line at the beginning of the file:
# -*- coding: utf-8 -*-
A sample plot is provided to prove the correctness of the code:
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
data = np.random.randn(5000) #generate some random data
plt.plot(data)
plt.title(u"Τίτλος του γραφήματος", fontproperties=fp1)
plt.xlabel(u"Άξονας x", fontproperties=fp1)
plt.ylabel(u"Άξονας y", fontproperties=fp1)
plt.show()
It should give you something like that:

Render vector letter in python

I would like to render a truetype letter to be used with the shapely module in python. (Say that I wish to make some morphologic operation on letters.)
Up to now, I managed to write a letter to a SVG file using cairo (see below). The letter is saved as a curve in the file header. The curve is basically what I need, but I believe there must be a much more elegant way to get the curve than to save, process and load a SVG file.
A second task is to load the curve in the format that shapely works with, but I think this can be done.
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import cairo
fo = file('test.svg', 'w')
WIDTH, HEIGHT = 256, 256
surface = cairo.SVGSurface (fo, WIDTH, HEIGHT) ## Prepare a destination surface -> out to an SVG file!
ctx = cairo.Context (surface)
ctx.scale (WIDTH/1.0, HEIGHT/1.0) # Normalizing the canvas
ctx.move_to (0.1, 0.9)
ctx.set_font_size(1.)
character = "a"
ctx.show_text(character)
surface.finish()
Thank you in advance for your tips!
EDIT: I figured out that instead of show_text() one may draw a real curve using text_path(), but still I cannot read the points...
print ctx.text_path("b")
ctx.set_source_rgb (0.3, 0.2, 0.5) # Solid color
ctx.set_line_width (0.02)
ctx.stroke ()
EDIT2:
With a help of my colleague we managed to get a similar result as above. Using fontforge it is also possible to render a glyph and save it to SVG (in Bezier curves). It may be useful to somebody.
#!/usr/bin/python
# -*- coding: utf-8 -*-
## Outputs a glyph as a SVG, using FontForge (requires package 'python-fontforge')
import fontforge
f = fontforge.open("/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf")
g = f["Aring"]
print g
g.export("orig.svg")
Optionally, one can already perform a morphologic dilation on the glyph before saving the SVG. (However, this is the only step of many that would be needed.)
g.stroke("circular", 100, "round", "round", "removeinternal") ## morphologic dilation of the glyph
g.export("stroke.svg")
Also the precise bounding box can be established.
print "Stroked: g.boundingBox() =", g.boundingBox()
By the way, trying to write even trivial Inkscape plugins is quite frustrating, but I still believe it is the best way for the task.
You'll probably need to use FreeType directly. The glyph-vector.py example shows how to get at the glyph vector information.

Reportlab: Asian fonts with encryption enabled does not work

I have been using Asian fonts (Chinese simplified/tradional, Japanese, and Korean) in my reportlab generated pdfs without issuse for a while now. However recently we have decided to enable the encryption options like this:
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
pdfmetrics.registerFont(UnicodeCIDFont("STSong-Light"))
enc = pdfencrypt.StandardEncryption(
"", canPrint=1, canModify=0, canCopy=0, canAnnotate=0
)
self._Report = SimpleDocTemplate(
save_file,
topmargin=0.75*inch, bottommargin=0.75*inch,
rightmargin=0.70*inch, leftmargin=0.70*inch,
showBoundary=0,
author="xxx",
title="xxx",
subject=xxx",
encrypt=enc
)
For non Asian languages the encryption works as expected. When we use Asian fonts with encryption the pdf cannot be read by adobe reader. For example with simplified Chinese we get a "Cannot find the font "STSong-Light" error from Adobe Reader.
Anyone have any ideas on what encryption is breaking to not make this work?
I had the same problem. This might not solve your problem.
But, If I specify it into Japanese,
you can solve it by installing TTFont(in this example it is IPA gothic),
and set the font.
So, by installing another languages fonts, you can solve the problem though
this is not cool.
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter,A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
fontname = 'IPA Gothic'
pdfmetrics.registerFont(TTFont(fontname,'{directory that you put the font}/ipag.ttf'))
p = canvas.Canvas(response,pagesize=A4)
p.setFont(fonatname,13)
p.drawString(100,100,u'日本語,中国語,韓国語')
p.showPage()
p.save()

Categories