Skip to content

Commit

Permalink
Improve register_font
Browse files Browse the repository at this point in the history
- Introduce `RegisterFont` dataclass to store font information
- Only registers fonts registered using win32 backend
- Other methods also only handles what it needs to
  • Loading branch information
naveen521kk committed Sep 11, 2024
1 parent 85893e0 commit 4326089
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 23 deletions.
45 changes: 31 additions & 14 deletions manimpango/_register_font.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@ from pathlib import Path
from pango cimport *

import os
import warnings
from dataclasses import dataclass

include "utils.pxi"

@dataclass(frozen=True)
class RegisteredFont:
"""A class to represent a font file.
Attributes
----------
path : :class:`str`
The path to the font file.
"""

path: str
type: "fontconfig" | "win32" | "macos"

cpdef bint _fc_register_font(set registered_fonts, str font_path):
a = Path(font_path)
assert a.exists(), f"font doesn't exist at {a.absolute()}"
Expand All @@ -14,15 +27,20 @@ cpdef bint _fc_register_font(set registered_fonts, str font_path):
cdef const unsigned char* fontPath = font_path_bytes
fontAddStatus = FcConfigAppFontAddFile(FcConfigGetCurrent(), fontPath)
if fontAddStatus:
registered_fonts.add(font_path)
registered_fonts.add(RegisteredFont(font_path, "fontconfig"))
return True
else:
return False


cpdef bint _fc_unregister_font(set registered_fonts, str font_path):
FcConfigAppFontClear(NULL)
registered_fonts.clear()
# remove all type "fontconfig" files
copy = registered_fonts.copy()
for font in copy:
if font.type == 'fontconfig':
registered_fonts.remove(font)

return True


Expand All @@ -43,12 +61,8 @@ ELIF UNAME_SYSNAME == "Windows":
0
)

# add to registered_fonts even if it fails
# since there's another new API where it's registered again
registered_fonts.add(font_path)


if fontAddStatus > 0:
registered_fonts.add(RegisteredFont(font_path, "win32"))
return True
else:
return False
Expand All @@ -59,8 +73,9 @@ ELIF UNAME_SYSNAME == "Windows":
assert a.exists(), f"font doesn't exist at {a.absolute()}"
font_path = os.fspath(a.absolute())

if font_path in registered_fonts:
registered_fonts.remove(font_path)
font = RegisteredFont(font_path, "win32")
if font in registered_fonts:
registered_fonts.remove(font)

cdef LPCWSTR wchar_path = PyUnicode_AsWideCharString(font_path, NULL)
return RemoveFontResourceExW(
Expand All @@ -84,7 +99,7 @@ ELIF UNAME_SYSNAME == "Darwin":
NULL
)
if res:
registered_fonts.add(os.fspath(a.absolute()))
registered_fonts.add(RegisteredFont(os.fspath(a.absolute()), "macos"))
return True
else:
return False
Expand All @@ -103,8 +118,9 @@ ELIF UNAME_SYSNAME == "Darwin":
NULL
)
if res:
if font_path in registered_fonts:
registered_fonts.remove(os.fspath(a.absolute()))
font = RegisteredFont(os.fspath(a.absolute()), "macos")
if font in registered_fonts:
registered_fonts.remove(font)
return True
else:
return False
Expand All @@ -116,7 +132,8 @@ cpdef list _list_fonts(tuple registered_fonts):
raise MemoryError("Pango.FontMap can't be created.")

for font in registered_fonts:
add_to_fontmap(fontmap, font)
if font.type == 'win32':
add_to_fontmap(fontmap, font.path)

cdef int n_families=0
cdef PangoFontFamily** families=NULL
Expand Down
10 changes: 6 additions & 4 deletions manimpango/cmanimpango.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ def text2svg(
layout = pango_cairo_create_layout(cr)
fontmap = pango_context_get_font_map (pango_layout_get_context (layout));

for font_path in registered_fonts:
add_to_fontmap(fontmap, font_path)
for font_item in registered_fonts:
if font_item.type == 'win32':
add_to_fontmap(fontmap, font_item.path)

if layout == NULL:
cairo_destroy(cr)
Expand Down Expand Up @@ -245,8 +246,9 @@ class MarkupUtils:

fontmap = pango_context_get_font_map (pango_layout_get_context (layout));

for font_path in registered_fonts:
add_to_fontmap(fontmap, font_path)
for font_item in registered_fonts:
if font_item.type == 'win32':
add_to_fontmap(fontmap, font_item.path)

if pango_width is None:
pango_layout_set_width(layout, pango_units_from_double(width))
Expand Down
11 changes: 8 additions & 3 deletions manimpango/register_font.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from __future__ import annotations

from functools import cache
from dataclasses import dataclass

from ._register_font import (
_fc_register_font,
_fc_unregister_font,
_list_fonts,
_register_font,
_unregister_font,
) # noqa: F403,F401
RegisteredFont,
)

__all__ = [
"fc_register_font",
Expand All @@ -15,10 +19,11 @@
"register_font",
"unregister_font",
"registered_fonts",
"RegisteredFont",
]

# An set of all registered font paths
registered_fonts = set()
registered_fonts: set[RegisteredFont] = set()


def fc_register_font(font_path: str) -> None:
Expand Down Expand Up @@ -146,4 +151,4 @@ def list_fonts() -> list:
:class:`list` :
List of fonts sorted alphabetically.
"""
return cache(_list_fonts)(tuple(sorted(registered_fonts)))
return cache(_list_fonts)(tuple(sorted(registered_fonts, key=lambda x: x.path)))
3 changes: 1 addition & 2 deletions tests/test_fonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,8 @@ def test_adding_dummy_font(tmpdir):
dummy = tmpdir / "font.ttf"
with open(dummy, "wb") as f:
f.write(b"dummy")

assert not manimpango.register_font(str(dummy)), "Registered a dummy font?"
assert not manimpango.fc_register_font(str(dummy)), "Registered a dummy font?"


def test_simple_fonts_render(tmpdir):
filename = str(Path(tmpdir) / "hello.svg")
Expand Down

0 comments on commit 4326089

Please sign in to comment.