Ответ 1
Этот вопрос завораживал меня всей неделей, так как на выходных я нырнул прямо в него и нашел решение, которое я назвал MultiFontParagraph
, это нормальный Paragraph
с большой разницей, вы можете точно установить отступ шрифта порядок.
Например, этот случайный японский текст, который я вытащил из Интернета, использовал следующий резерв шрифта "Bauhaus", "Arial", "HanaMinA"
. Он проверяет, имеет ли первый шрифт глиф для символа, если он его использует, если он не возвращается к следующему шрифту. В настоящее время код не очень эффективен, поскольку он помещает теги вокруг каждого символа, это можно легко устранить, но для ясности я этого не делал.
Используя следующий код, я создал приведенный выше пример:
foreign_string = u'6905\u897f\u963f\u79d1\u8857\uff0c\u5927\u53a6\uff03\u5927'
P = MultiFontParagraph(foreign_string, styles["Normal"],
[ ("Bauhaus", "C:\Windows\Fonts\\BAUHS93.TTF"),
("Arial", "C:\Windows\Fonts\\arial.ttf"),
("HanaMinA", 'C:\Windows\Fonts\HanaMinA.ttf')])
Источник MultiFontParagraph
(git) выглядит следующим образом:
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.platypus import Paragraph
class MultiFontParagraph(Paragraph):
# Created by B8Vrede for http://stackoverflow.com/questions/35172207/
def __init__(self, text, style, fonts_locations):
font_list = []
for font_name, font_location in fonts_locations:
# Load the font
font = TTFont(font_name, font_location)
# Get the char width of all known symbols
font_widths = font.face.charWidths
# Register the font to able it use
pdfmetrics.registerFont(font)
# Store the font and info in a list for lookup
font_list.append((font_name, font_widths))
# Set up the string to hold the new text
new_text = u''
# Loop through the string
for char in text:
# Loop through the fonts
for font_name, font_widths in font_list:
# Check whether this font know the width of the character
# If so it has a Glyph for it so use it
if ord(char) in font_widths:
# Set the working font for the current character
new_text += u'<font name="{}">{}</font>'.format(font_name, char)
break
Paragraph.__init__(self, new_text, style)