Подтвердить что ты не робот

ReportLab: работа с символами китайского/Юникода

TL; ДР: Есть ли способ сообщить ReportLab использовать конкретный шрифт и отступить к другому, если отсутствуют символы глифов для некоторых символов? Альтернативно, Знаете ли вы о конденсированном шрифте TrueType, который содержит глифы для все европейские языки, иврит, русский, китайский, японский и арабский?

Я создавал отчеты с ReportLab и столкнулся с проблемами с строк перевода, содержащих китайские символы. Шрифт, который я использовал, - DejaVu Sans Condensed, который не содержит глифов для китайцев (однако он содержит кириллицу, иврит, арабский язык и всевозможные Umlauts для поддержки европейского языка, что делает его довольно универсальным, и мне нужно все они время от времени)

Однако китайский шрифт не поддерживается шрифтом, и я не смог найти шрифт TrueType, который поддерживает ВСЕ языки, и соответствует нашим требованиям графического дизайна. В качестве временного решения я сделал так, чтобы в отчетах для китайских клиентов использовался совершенно другой шрифт, содержащий только английские и китайские глифы, надеясь, что символы на других языках не будут присутствовать в строках. Однако по понятным причинам это неудобно и ломает графический дизайн, поскольку это не DejaVu Sans, вокруг которого дизайн всего взгляда и дизайна был спроектирован.

Итак, вопрос:, как бы вы справились с необходимостью поддерживать несколько языков в одном документе и поддерживать использование указанного шрифта для каждого языка. Это усложняется из-за того, что иногда строки содержат сочетание языков, поэтому определение того, какой символ ONE следует использовать для каждой строки, не является вариантом.

Есть ли способ сообщить ReportLab использовать конкретный шрифт и отступить к другому, если отсутствуют символы глифов для некоторых символов? Я нашел неопределенные намеки в документах, что это должно быть возможно, хотя я могу понять это неправильно.

В качестве альтернативы, знаете ли вы о конденсированном шрифте TrueType, который содержит глифы для всех европейских языков, иврит, русский, китайский, японский и арабский?

Спасибо.

4b9b3361

Ответ 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)

Ответ 2

Из Google Noto Fonts:

Google разрабатывает семейство шрифтов под названием Noto, целью которого является поддержка всех языков с гармоничным внешним видом.

унифицированный шрифт Noto Sans включает в себя один шрифт, поддерживающий 581 язык из следующих областей:

введите описание изображения здесь

Другие, такие как иврит, арабский и японский, перечислены как отдельные элементы на веб-сайте Noto.