Skip to content

Slavic characters are replaced by ■ #792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Netvia opened this issue Jan 16, 2025 · 1 comment
Open

Slavic characters are replaced by ■ #792

Netvia opened this issue Jan 16, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@Netvia
Copy link

Netvia commented Jan 16, 2025

Describe the Bug

Slavic characters are replaced by ■. Standard Arial font knows this letters, where should be an error?

pdf is created with unreadable chars. I also tried updated this html (with file "arial.ttf" in the same directory), but there is the same ouptut:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
            <title>My HTML Document</title>
            <style>
                @font-face {
                    font-family: Arial;
                    src: url('/arial.ttf');
                }
                *{
                    font-family: Arial;
                    color: red;
                    }
            </style
        </head>
    <body>
        <h1>+ěščřžýáíéí</h1>
    </body>
</html>

Minimal Example to Reproduce

file input.html :

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
            <title>My HTML Document</title>
            <style>
                *{
                    font-family: Arial;
                    color: red;
                    }
            </style
        </head>
    <body>
        <h1>+ěščřžýáíéí</h1>
    </body>
</html>

python code (utf-8 enconding too):

  OUT = "output.pdf"
  IN = "input.html"

  from xhtml2pdf import pisa
  with open(IN, 'r', encoding='utf-8') as html_file:
      html_content = html_file.read()

  with open(OUT, 'wb') as pdf_file:
      pisa_status = pisa.CreatePDF(html_content, dest=pdf_file, encoding='utf-8')

  if pisa_status.err:
      return False

Expected Behavior

+ěščřžýáíéí

Actual Behavior

+■š■■žýáíéí

System Information

OS version: Windows 11 24H2
Python version: 3.13.0, also on 3.10.7
XHTML2PDF version: 0.2.16

@Netvia Netvia added the bug Something isn't working label Jan 16, 2025
@PiotrCzapla
Copy link

PiotrCzapla commented Mar 20, 2025

it seems the font is missing this character set, claude-code figure out a solution on its :), here is a working example:

import urllib.request
from io import BytesIO

from xhtml2pdf import pisa

font_url = "https://github.com/notofonts/noto-fonts/raw/main/hinted/ttf/NotoSans/NotoSans-Regular.ttf"
font_path = "./NotoSans-Regular.ttf"
# it is used by link_callback to find the font file
urllib.request.urlretrieve(font_url, font_path)

html = """
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <style>
        @font-face {
            font-family: 'NotoSans-Regular';
            src: url('{{font_url}}');
        }

        body {
            font-family: NotoSans-Regular, Arial, sans-serif;
            font-size: 10pt;
            line-height: 1.5;
            color: #333;
        }
        
        
        h1 {
            font-size: 18px;
            font-weight: bold;
        }
        
        .test-section {
            margin: 20px 0;
            padding: 10px;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>

    <h1>UTF-8 and Font Test</h1>
    
    <div class="test-section">
        <h2>Polish Characters:</h2>
        <p>ąćęłńóśźż ĄĆĘŁŃÓŚŹŻ</p>
    </div>
    
    <div class="test-section">
        <h2>Czech Characters:</h2>
        <p>ěščřžýáíéů ĚŠČŘŽÝÁÍÉŮ</p>
    </div>
    
    <div class="test-section">
        <h2>Russian Characters:</h2>
        <p>абвгдеёжзийклмнопрстуфхцчшщъыьэюя</p>
        <p>АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ</p>
    </div>
    
    <div class="test-section">
        <h2>Additional Test:</h2>
        <p>zażółć gęślą jaźń</p>
    </div>
</body>
</html>
""".replace(
    "{{font_url}}", font_url
)


# this bit is crucial to make the font work
def link_callback(uri, rel):
    if uri.startswith("file:///"):
        path = uri[7:]
        return path
    if uri == font_url:
        return "NotoSans-Regular.ttf"
    return uri


# Convert HTML to PDF
pdf_data = BytesIO()
conversion_result = pisa.CreatePDF(
    html, dest=pdf_data, encoding="UTF-8", link_callback=link_callback
)

# Check for errors
if conversion_result.err:
    print(f"Error during PDF creation: {conversion_result.err}")
else:
    # Write PDF to file
    with open("test_noto_font.pdf", "wb") as f:
        f.write(pdf_data.getvalue())
    print("PDF created: test_noto_font.pdf")

I've simplified the Claude-code solution to the relevant bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants