|
16 | 16 | from functools import lru_cache
|
17 | 17 | import re
|
18 | 18 |
|
19 |
| -from pyparsing import (Literal, ZeroOrMore, Optional, Regex, StringEnd, |
20 |
| - ParseException, Suppress) |
21 |
| - |
22 | 19 | family_punc = r'\\\-:,'
|
23 | 20 | family_unescape = re.compile(r'\\([%s])' % family_punc).sub
|
24 | 21 | family_escape = re.compile(r'([%s])' % family_punc).sub
|
|
27 | 24 | value_unescape = re.compile(r'\\([%s])' % value_punc).sub
|
28 | 25 | value_escape = re.compile(r'([%s])' % value_punc).sub
|
29 | 26 |
|
| 27 | +_SIMPLE_PATTERN_CACHE = { |
| 28 | + 'cursive': {'family': ['cursive']}, |
| 29 | + 'sans': {'family': ['sans']}, |
| 30 | + 'monospace': {'family': ['monospace']}, |
| 31 | + 'sans:italic': {'family': ['sans'], 'slant': ['italic']}, |
| 32 | + 'sans:bold': {'family': ['sans'], 'weight': ['bold']}, |
| 33 | +} |
| 34 | + |
30 | 35 |
|
31 | 36 | class FontconfigPatternParser(object):
|
32 | 37 | """A simple pyparsing-based parser for fontconfig-style patterns.
|
@@ -64,6 +69,10 @@ class FontconfigPatternParser(object):
|
64 | 69 | }
|
65 | 70 |
|
66 | 71 | def __init__(self):
|
| 72 | + # delayed import. Only executed when needed |
| 73 | + from pyparsing import (Literal, ZeroOrMore, Optional, Regex, StringEnd, |
| 74 | + ParseException, Suppress) |
| 75 | + |
67 | 76 | family = Regex(r'([^%s]|(\\[%s]))*' %
|
68 | 77 | (family_punc, family_punc)) \
|
69 | 78 | .setParseAction(self._family)
|
@@ -162,11 +171,33 @@ def _property(self, s, loc, tokens):
|
162 | 171 | return []
|
163 | 172 |
|
164 | 173 |
|
| 174 | +@lru_cache(maxsize=1) |
| 175 | +def _get_parser(): |
| 176 | + """Return a cached FontconfigPatternParser instance.""" |
| 177 | + return FontconfigPatternParser() |
| 178 | + |
| 179 | + |
165 | 180 | # `parse_fontconfig_pattern` is a bottleneck during the tests because it is
|
166 | 181 | # repeatedly called when the rcParams are reset (to validate the default
|
167 | 182 | # fonts). In practice, the cache size doesn't grow beyond a few dozen entries
|
168 | 183 | # during the test suite.
|
169 |
| -parse_fontconfig_pattern = lru_cache()(FontconfigPatternParser().parse) |
| 184 | +@lru_cache() |
| 185 | +def parse_fontconfig_pattern(pattern): |
| 186 | + """ |
| 187 | + Parse the given fontconfig *pattern* and return a dictionary |
| 188 | + of key/value pairs useful for initializing a |
| 189 | + :class:`font_manager.FontProperties` object. |
| 190 | + """ |
| 191 | + |
| 192 | + # Try a lookup on simple patterns first. This can prevent the need to |
| 193 | + # create a full parser and to import pyparsing. If only patterns from |
| 194 | + # _SIMPLE_PATTERN_CACHE are used in the matplotlibrc file, this will |
| 195 | + # speed up the import of matplotlib. |
| 196 | + parsed = _SIMPLE_PATTERN_CACHE.get(pattern) |
| 197 | + if parsed is not None: |
| 198 | + return parsed |
| 199 | + |
| 200 | + return _get_parser().parse(pattern) |
170 | 201 |
|
171 | 202 |
|
172 | 203 | def generate_fontconfig_pattern(d):
|
|
0 commit comments