-
Notifications
You must be signed in to change notification settings - Fork 45
Add a way for applications to supply custom fonts #711
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
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
78296fa
Add a way for applications to supply custom fonts
jwiggins c076917
Add fontconfig to the ubuntu CI dependencies
jwiggins 5603d77
Don't need to install fontconfig; Do need a different check
jwiggins ecaf8ca
Add PYTHONFAULTHANDLER for test runs on CI
jwiggins 4ab0077
PR feedback
jwiggins 72b613c
Only test GL backend on linux
jwiggins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,6 +109,43 @@ def scan_system_fonts(fontpaths=None, fontext="ttf"): | |
| return [fname for fname in fontfiles if os.path.exists(fname)] | ||
|
|
||
|
|
||
| def scan_user_fonts(fontpaths=None, fontext="ttf"): | ||
| """ Search for fonts in the specified font paths. | ||
|
|
||
| Returns | ||
| ------- | ||
| filepaths : list of str | ||
| A list of unique font file paths. | ||
| """ | ||
| if fontpaths is None: | ||
| return [] | ||
|
|
||
| if isinstance(fontpaths, str): | ||
| fontpaths = [fontpaths] | ||
|
|
||
| fontfiles = set() | ||
| fontexts = _get_fontext_synonyms(fontext) | ||
| for path in fontpaths: | ||
| path = os.path.abspath(path) | ||
| if os.path.isdir(path): | ||
| # For directories, find all the fonts within | ||
| files = [] | ||
| for ext in fontexts: | ||
| files.extend(glob.glob(os.path.join(path, "*." + ext))) | ||
| files.extend(glob.glob(os.path.join(path, "*." + ext.upper()))) | ||
|
|
||
| for fname in files: | ||
| if os.path.exists(fname) and not os.path.isdir(fname): | ||
| fontfiles.add(fname) | ||
| elif os.path.exists(path): | ||
| # For files, make sure they have the correct extension | ||
| ext = os.path.splitext(path)[-1][1:].lower() | ||
| if ext in fontexts: | ||
| fontfiles.add(path) | ||
|
|
||
| return sorted(fontfiles) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't know that sorting a set will return a list - in case anyone was wondering if it'll be a problem that we're returning an empty list above but a sorted set here. |
||
|
|
||
|
|
||
| # ---------------------------------------------------------------------------- | ||
| # utility funcs | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # (C) Copyright 2005-2021 Enthought, Inc., Austin, TX | ||
| # All rights reserved. | ||
| # | ||
| # This software is provided without warranty under the terms of the BSD | ||
| # license included in LICENSE.txt and may be redistributed only under | ||
| # the conditions described in the aforementioned license. The license | ||
| # is also available online at http://www.enthought.com/licenses/BSD.txt | ||
| # | ||
| # Thanks for using Enthought open source! | ||
| import warnings | ||
|
|
||
| from traits.etsconfig.api import ETSConfig | ||
|
|
||
| from kiva.fonttools.font_manager import default_font_manager | ||
|
|
||
|
|
||
| def add_application_fonts(filenames): | ||
| """ Add a TrueType font to the system in a way that makes it available to | ||
| both the GUI toolkit and Kiva. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| filenames : list of str | ||
| Filesystem paths of TrueType or OpenType font files. | ||
| """ | ||
| if isinstance(filenames, str): | ||
| filenames = [filenames] | ||
|
|
||
| # Handle Kiva | ||
| fm = default_font_manager() | ||
| fm.update_fonts(filenames) | ||
|
|
||
| # Handle the GUI toolkit | ||
| if ETSConfig.toolkit.startswith("qt"): | ||
| _qt_impl(filenames) | ||
| elif ETSConfig.toolkit == "wx": | ||
| _wx_impl(filenames) | ||
|
|
||
|
|
||
| def _qt_impl(filenames): | ||
| from pyface.qt import QtGui | ||
|
|
||
| for fname in filenames: | ||
| QtGui.QFontDatabase.addApplicationFont(fname) | ||
|
|
||
|
|
||
| def _wx_impl(filenames): | ||
| import wx | ||
|
|
||
| if hasattr(wx.Font, "CanUsePrivateFont") and wx.Font.CanUsePrivateFont(): | ||
| for fname in filenames: | ||
| wx.Font.AddPrivateFont(fname) | ||
| else: | ||
| warnings.warn("Wx does not support private fonts! Failed to add.") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # (C) Copyright 2005-2021 Enthought, Inc., Austin, TX | ||
| # All rights reserved. | ||
| # | ||
| # This software is provided without warranty under the terms of the BSD | ||
| # license included in LICENSE.txt and may be redistributed only under | ||
| # the conditions described in the aforementioned license. The license | ||
| # is also available online at http://www.enthought.com/licenses/BSD.txt | ||
| # | ||
| # Thanks for using Enthought open source! | ||
| import os | ||
| import unittest | ||
|
|
||
| import pkg_resources | ||
|
|
||
| from traits.etsconfig.api import ETSConfig | ||
|
|
||
| from kiva.api import add_application_fonts, Font | ||
|
|
||
| is_null = (ETSConfig.toolkit in ("", "null")) | ||
| is_qt = ETSConfig.toolkit.startswith("qt") | ||
| is_wx = (ETSConfig.toolkit == "wx") | ||
| data_dir = pkg_resources.resource_filename("kiva.fonttools.tests", "data") | ||
|
|
||
|
|
||
| @unittest.skipIf(not is_null, "Test only for null toolkit") | ||
| class TestNullApplicationFonts(unittest.TestCase): | ||
| def test_add_application_font(self): | ||
| path = os.path.join(data_dir, "TestTTF.ttf") | ||
| family = "Test TTF" | ||
| kivafont = Font(family) | ||
|
|
||
| # Before adding the font | ||
| with self.assertWarns(UserWarning): | ||
| self.assertNotEqual(kivafont.findfont().filename, path) | ||
|
|
||
| add_application_fonts([path]) | ||
|
|
||
| # After adding the font | ||
| self.assertEqual(kivafont.findfont().filename, path) | ||
|
|
||
|
|
||
| @unittest.skipIf(not is_qt, "Test only for qt") | ||
| class TestQtApplicationFonts(unittest.TestCase): | ||
| def setUp(self): | ||
| from pyface.qt import QtGui | ||
|
|
||
| application = QtGui.QApplication.instance() | ||
| if application is None: | ||
| self.application = QtGui.QApplication([]) | ||
| else: | ||
| self.application = application | ||
| unittest.TestCase.setUp(self) | ||
|
|
||
| def test_add_application_font(self): | ||
| from pyface.qt import QtGui | ||
|
|
||
| path = os.path.join(data_dir, "TestTTF.ttf") | ||
| family = "Test TTF" | ||
| font_db = QtGui.QFontDatabase() | ||
|
|
||
| # Before adding the font | ||
| self.assertNotIn(family, font_db.families()) | ||
|
|
||
| add_application_fonts([path]) | ||
|
|
||
| # After adding the font | ||
| self.assertIn(family, font_db.families()) | ||
|
|
||
|
|
||
| @unittest.skipIf(not is_wx, "Test only for wx") | ||
| class TestWxApplicationFonts(unittest.TestCase): | ||
| def setUp(self): | ||
| import wx | ||
|
|
||
| application = wx.App.Get() | ||
| if application is None: | ||
| self.application = wx.App() | ||
| else: | ||
| self.application = application | ||
| unittest.TestCase.setUp(self) | ||
|
|
||
| # XXX: How do we check to see if Wx loaded our font? | ||
| @unittest.expectedFailure | ||
| def test_add_application_font(self): | ||
| import wx | ||
|
|
||
| path = os.path.join(data_dir, "TestTTF.ttf") | ||
| family = "Test TTF" | ||
|
|
||
| fontinfo = wx.FontInfo() | ||
| fontinfo.FaceName(family) | ||
| wxfont = wx.Font(fontinfo) | ||
|
|
||
| # Before adding the font | ||
| self.assertFalse(wxfont.IsOk()) | ||
|
|
||
| add_application_fonts([path]) | ||
|
|
||
| # After adding the font | ||
| self.assertTrue(wxfont.IsOk()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.