]>
git.immae.eu Git - perso/Immae/Projets/Python/MusicSampler.git/blob - music_sampler/sysfont.py
1 # This file was imported from
2 # https://bitbucket.org/marcusva/python-utils/overview
5 """OS-specific font detection."""
8 from subprocess
import Popen
, PIPE
10 if sys
.platform
in ("win32", "cli"):
13 __all__
= ["STYLE_NORMAL", "STYLE_BOLD", "STYLE_ITALIC", "STYLE_LIGHT",
14 "init", "list_fonts", "get_fonts", "get_font"
19 # (name, styles, fonttype, filename)
33 def _add_font(family
, name
, styles
, fonttype
, filename
):
34 """Adds a font to the internal font cache."""
37 if family
not in __FONTCACHE
:
38 __FONTCACHE
[family
] = []
39 __FONTCACHE
[family
].append((name
, styles
, fonttype
, filename
))
42 def _cache_fonts_win32():
43 """Caches fonts on a Win32 platform."""
44 key
= "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
47 with winreg
.OpenKey(winreg
.HKEY_LOCAL_MACHINE
, key
) as fontkey
:
49 enumval
= winreg
.EnumValue
50 rappend
= regfonts
.append
52 rappend(enumval(fontkey
, idx
)[:2])
57 # TODO: integrate alias handling for fonts within the registry.
58 # TODO: Scan and index fonts from %SystemRoot%\\Fonts that are not in the
61 # Received all fonts from the registry.
62 for name
, filename
in regfonts
:
63 fonttype
= os
.path
.splitext(filename
)[1][1:].lower()
64 if name
.endswith("(TrueType)"):
65 name
= name
[:-10].strip()
66 if name
.endswith("(All Res)"):
67 name
= name
[:-9].strip()
69 if name
.find(" Bold") >= 0:
71 if name
.find(" Italic") >= 0 or name
.find(" Oblique") >= 0:
75 for rm
in ("Bold", "Italic", "Oblique"):
76 family
= family
.replace(rm
, "")
77 family
= family
.lower().strip()
79 fontpath
= os
.environ
.get("SystemRoot", "C:\\Windows")
80 fontpath
= os
.path
.join(fontpath
, "Fonts")
81 if filename
.find("\\") == -1:
82 # No path delimiter is given; we assume it to be a font in
84 filename
= os
.path
.join(fontpath
, filename
)
85 _add_font(family
, name
, style
, fonttype
, filename
)
88 def _cache_fonts_darwin():
89 """Caches fonts on Mac OS."""
90 raise NotImplementedError("Mac OS X support is not given yet")
93 def _cache_fonts_fontconfig():
94 """Caches font on POSIX-alike platforms."""
96 command
= "fc-list : file family style fullname fullnamelang"
97 proc
= Popen(command
, stdout
=PIPE
, shell
=True, stderr
=PIPE
)
98 pout
= proc
.communicate()[0]
99 output
= pout
.decode("utf-8")
103 for entry
in output
.split(os
.linesep
):
104 if entry
.strip() == "":
106 values
= entry
.split(":")
110 fname
, fonttype
= os
.path
.splitext(filename
)
111 if fonttype
== ".gz":
112 fonttype
= os
.path
.splitext(fname
)[1][1:].lower()
114 fonttype
= fonttype
.lstrip(".").lower()
119 fullnames
, fullnamelangs
= values
[3:]
120 langs
= fullnamelangs
.split(",")
122 offset
= langs
.index("fullnamelang=en")
127 offset
= langs
.index("en")
131 # got an english name, use that one
132 name
= fullnames
.split(",")[offset
]
133 if name
.startswith("fullname="):
136 if fname
.endswith(".pcf") or fname
.endswith(".bdf"):
137 name
= os
.path
.basename(fname
[:-4])
139 name
= os
.path
.basename(fname
)
143 family
= values
[1].strip().lower()
145 stylevals
= values
[2].strip()
150 if stylevals
.find("Bold") >= 0:
152 if stylevals
.find("Light") >= 0:
154 if stylevals
.find("Italic") >= 0 or stylevals
.find("Oblique") >= 0:
155 style |
= STYLE_ITALIC
156 if stylevals
.find("Medium") >= 0:
157 style |
= STYLE_MEDIUM
158 if style
== STYLE_NONE
:
160 _add_font(family
, name
, style
, fonttype
, filename
)
164 """Initialises the internal font cache.
166 It does not need to be called explicitly.
169 if __FONTCACHE
is not None:
172 if sys
.platform
in ("win32", "cli"):
174 elif sys
.platform
== "darwin":
175 _cache_fonts_darwin()
177 _cache_fonts_fontconfig()
181 """Returns an iterator over the cached fonts."""
182 if __FONTCACHE
is None:
184 if len(__FONTCACHE
) == 0:
186 for family
, entries
in __FONTCACHE
.items():
187 for fname
, styles
, fonttype
, filename
in entries
:
188 yield (family
, fname
, styles
, fonttype
, filename
)
191 def get_fonts(name
, style
=STYLE_NONE
, ftype
=None):
192 """Retrieves all fonts matching the given family or font name."""
193 if __FONTCACHE
is None:
195 if len(__FONTCACHE
) == 0:
199 rappend
= results
.append
203 ftype
= ftype
.lower()
205 fonts
= __FONTCACHE
.get(name
, [])
206 for fname
, fstyles
, fonttype
, filename
in fonts
:
207 if ftype
and fonttype
!= ftype
:
208 # ignore font filetype mismatches
210 if style
== STYLE_NONE
or fstyles
== style
:
211 rappend((name
, fname
, fstyles
, fonttype
, filename
))
213 for family
, fonts
in __FONTCACHE
.items():
214 for fname
, fstyles
, fonttype
, filename
in fonts
:
215 if fname
.lower() == name
and filename
not in results
:
216 rappend((family
, fname
, fstyles
, fonttype
, filename
))
220 def get_font(name
, style
=STYLE_NONE
, ftype
=None):
221 """Retrieves the best matching font file for the given name and
224 retvals
= get_fonts(name
, style
, ftype
)