ReportLab: working with Chinese/Unicode characters

前端 未结 2 1605
既然无缘
既然无缘 2021-01-01 14:46

TL;DR: Is there some way of telling ReportLab to use a specific font, and fallback to another if glyphs for some characters are missing? Alternatively, Do you kno

相关标签:
2条回答
  • 2021-01-01 15:45

    This question fascinated me the complete week, so since it is weekend I dived right into it and exactly found a solution which I called MultiFontParagraph it is a normal Paragraph with one big difference you can exactly set a font fallback order.

    For example this random Japanese text I pulled of the internet used the following font fallback "Bauhaus", "Arial", "HanaMinA". It checks whether the first font has a glyph for the character, if so it uses it, if not it fallsback to the next font. Currently the code isn't really efficient as it places tags around each character, this can easily be fixed but for clarity I didn't do it here.

    Using the following code I created the above example:

    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')])
    

    The source of the MultiFontParagraph (git) is as follows:

    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)
    
    0 讨论(0)
  • 2021-01-01 15:46

    From Google Noto Fonts:

    Google has been developing a font family called Noto, which aims to support all languages with a harmonious look and feel.

    The unified Noto Sans font includes a single font, supporting 581 languages from the following areas:

    Others such as Hebrew, Arabic and Japanese are listed as separate items on the Noto website.

    0 讨论(0)
提交回复
热议问题