Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Make "classic" style have effect #5437

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 3 commits into from
Nov 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/matplotlib/afm.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,10 @@ def get_familyname(self):
br'light|ultralight|extra|condensed))+$')
return re.sub(extras, '', name)

@property
def family_name(self):
return self.get_familyname()

def get_weight(self):
"Return the font weight, e.g., 'Bold' or 'Roman'"
return self._header[b'Weight']
Expand Down
197 changes: 127 additions & 70 deletions lib/matplotlib/mathtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -1240,58 +1240,115 @@ def get_underline_thickness(self, font, fontsize, dpi):
# The number of different sizes of chars to use, beyond which they will not
# get any smaller
NUM_SIZE_LEVELS = 6
# Percentage of x-height of additional horiz. space after sub/superscripts
SCRIPT_SPACE = {'cm': 0.075,
'stix': 0.10,
'stixsans': 0.05,
'dejavuserif': 0.05,
'dejavusans': 0.05}
## Percentage of x-height that sub/superscripts drop below the baseline
SUBDROP = {'cm': 0.2,
'stix': 0.4,
'stixsans': 0.4,
'dejavuserif': 0.4,
'dejavusans': 0.4}
# Percentage of x-height that superscripts are raised from the baseline
SUP1 = {'cm': 0.45,
'stix': 0.8,
'stixsans': 0.8,
'dejavuserif': 0.7,
'dejavusans': 0.7}
# Percentage of x-height that subscripts drop below the baseline
SUB1 = {'cm': 0.2,
'stix': 0.3,
'stixsans': 0.3,
'dejavuserif': 0.3,
'dejavusans': 0.3}
# Percentage of x-height that subscripts drop below the baseline when a
# superscript is present
SUB2 = {'cm': 0.3,
'stix': 0.6,
'stixsans': 0.5,
'dejavuserif': 0.5,
'dejavusans': 0.5}
# Percentage of x-height that sub/supercripts are offset relative to the
# nucleus edge for non-slanted nuclei
DELTA = {'cm': 0.075,
'stix': 0.05,
'stixsans': 0.025,
'dejavuserif': 0.025,
'dejavusans': 0.025}
# Additional percentage of last character height above 2/3 of the x-height that
# supercripts are offset relative to the subscript for slanted nuclei
DELTASLANTED = {'cm': 0.3,
'stix': 0.3,
'stixsans': 0.6,
'dejavuserif': 0.2,
'dejavusans': 0.2}
# Percentage of x-height that supercripts and subscripts are offset for
# integrals
DELTAINTEGRAL = {'cm': 0.3,
'stix': 0.3,
'stixsans': 0.3,
'dejavuserif': 0.1,
'dejavusans': 0.1}


class FontConstantsBase(object):
"""
A set of constants that controls how certain things, such as sub-
and superscripts are laid out. These are all metrics that can't
be reliably retrieved from the font metrics in the font itself.
"""
# Percentage of x-height of additional horiz. space after sub/superscripts
script_space = 0.05

# Percentage of x-height that sub/superscripts drop below the baseline
subdrop = 0.4

# Percentage of x-height that superscripts are raised from the baseline
sup1 = 0.7

# Percentage of x-height that subscripts drop below the baseline
sub1 = 0.3

# Percentage of x-height that subscripts drop below the baseline when a
# superscript is present
sub2 = 0.5

# Percentage of x-height that sub/supercripts are offset relative to the
# nucleus edge for non-slanted nuclei
delta = 0.025

# Additional percentage of last character height above 2/3 of the
# x-height that supercripts are offset relative to the subscript
# for slanted nuclei
delta_slanted = 0.2

# Percentage of x-height that supercripts and subscripts are offset for
# integrals
delta_integral = 0.1


class ComputerModernFontConstants(FontConstantsBase):
script_space = 0.075
subdrop = 0.2
sup1 = 0.45
sub1 = 0.2
sub2 = 0.3
delta = 0.075
delta_slanted = 0.3
delta_integral = 0.3


class STIXFontConstants(FontConstantsBase):
script_space = 0.1
sup1 = 0.8
sub2 = 0.6
delta = 0.05
delta_slanted = 0.3
delta_integral = 0.3


class STIXSansFontConstants(FontConstantsBase):
script_space = 0.05
sup1 = 0.8
delta_slanted = 0.6
delta_integral = 0.3


class DejaVuSerifFontConstants(FontConstantsBase):
pass


class DejaVuSansFontConstants(FontConstantsBase):
pass


# Maps font family names to the FontConstantBase subclass to use
_font_constant_mapping = {
'DejaVu Sans': DejaVuSansFontConstants,
'DejaVu Sans Mono': DejaVuSansFontConstants,
'DejaVu Serif': DejaVuSerifFontConstants,
'cmb10': ComputerModernFontConstants,
'cmex10': ComputerModernFontConstants,
'cmmi10': ComputerModernFontConstants,
'cmr10': ComputerModernFontConstants,
'cmss10': ComputerModernFontConstants,
'cmsy10': ComputerModernFontConstants,
'cmtt10': ComputerModernFontConstants,
'STIXGeneral': STIXFontConstants,
'STIXNonUnicode': STIXFontConstants,
'STIXSizeFiveSym': STIXFontConstants,
'STIXSizeFourSym': STIXFontConstants,
'STIXSizeThreeSym': STIXFontConstants,
'STIXSizeTwoSym': STIXFontConstants,
'STIXSizeOneSym': STIXFontConstants,
# Map the fonts we used to ship, just for good measure
'Bitstream Vera Sans': DejaVuSansFontConstants,
'Bitstream Vera': DejaVuSansFontConstants,
}


def _get_font_constant_set(state):
constants = _font_constant_mapping.get(
state.font_output._get_font(state.font).family_name,
FontConstantsBase)
# STIX sans isn't really its own fonts, just different code points
# in the STIX fonts, so we have to detect this one separately.
if (constants is STIXFontConstants and
isinstance(state.font_output, StixSansFonts)):
return STIXSansFontConstants
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tab this over one so that it doesn't line up with the code block.

Sorry, made that comment in the commit rather than the PR.

return constants


class MathTextWarning(Warning):
pass
Expand Down Expand Up @@ -2873,25 +2930,24 @@ def subsuper(self, s, loc, toks):
nucleus = Hlist([nucleus])

# Handle regular sub/superscripts

fs = rcParams['mathtext.fontset']
if fs == 'custom':
fs = 'dejavusans'

constants = _get_font_constant_set(state)
lc_height = last_char.height
lc_baseline = 0
if self.is_dropsub(last_char):
lc_baseline = last_char.depth

# Compute kerning for sub and super
superkern = DELTA[fs] * xHeight
subkern = DELTA[fs] * xHeight
superkern = constants.delta * xHeight
subkern = constants.delta * xHeight
if self.is_slanted(last_char):
superkern += DELTA[fs] * xHeight
superkern += DELTASLANTED[fs] * (lc_height - xHeight * 2. / 3.)
superkern += constants.delta * xHeight
superkern += (constants.delta_slanted *
(lc_height - xHeight * 2. / 3.))
if self.is_dropsub(last_char):
subkern = (3 * DELTA[fs] - DELTAINTEGRAL[fs]) * lc_height
superkern = (3 * DELTA[fs] + DELTAINTEGRAL[fs]) * lc_height
subkern = (3 * constants.delta -
constants.delta_integral) * lc_height
superkern = (3 * constants.delta +
constants.delta_integral) * lc_height
else:
subkern = 0

Expand All @@ -2900,26 +2956,26 @@ def subsuper(self, s, loc, toks):
x = Hlist([Kern(subkern), sub])
x.shrink()
if self.is_dropsub(last_char):
shift_down = lc_baseline + SUBDROP[fs] * xHeight
shift_down = lc_baseline + constants.subdrop * xHeight
else:
shift_down = SUB1[fs] * xHeight
shift_down = constants.sub1 * xHeight
x.shift_amount = shift_down
else:
x = Hlist([Kern(superkern), super])
x.shrink()
if self.is_dropsub(last_char):
shift_up = lc_height - SUBDROP[fs] * xHeight
shift_up = lc_height - constants.subdrop * xHeight
else:
shift_up = SUP1[fs] * xHeight
shift_up = constants.sup1 * xHeight
if sub is None:
x.shift_amount = -shift_up
else: # Both sub and superscript
y = Hlist([Kern(subkern),sub])
y.shrink()
if self.is_dropsub(last_char):
shift_down = lc_baseline + SUBDROP[fs] * xHeight
shift_down = lc_baseline + constants.subdrop * xHeight
else:
shift_down = SUB2[fs] * xHeight
shift_down = constants.sub2 * xHeight
# If sub and superscript collide, move super up
clr = (2.0 * rule_thickness -
((shift_up - x.depth) - (y.height - shift_down)))
Expand All @@ -2931,8 +2987,9 @@ def subsuper(self, s, loc, toks):
x.shift_amount = shift_down

if not self.is_dropsub(last_char):
x.width += SCRIPT_SPACE[fs] * xHeight
x.width += constants.script_space * xHeight
result = Hlist([nucleus, x])

return [result]

def _genfrac(self, ldelim, rdelim, rule, style, num, den):
Expand Down
6 changes: 3 additions & 3 deletions lib/matplotlib/mpl-data/stylelib/classic.mplstyle
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ font.stretch : normal
# relative to font.size, using the following values: xx-small, x-small,
# small, medium, large, x-large, xx-large, larger, or smaller
font.size : 12.0
font.serif : Bitstream Vera Serif, DejaVu Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
font.sans-serif: Bitstream Vera Sans, DejaVu Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif
font.serif : DejaVu Serif, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif
font.sans-serif: DejaVu Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif
font.cursive : Apple Chancery, Textile, Zapf Chancery, Sand, Script MT, Felipa, cursive
font.fantasy : Comic Sans MS, Chicago, Charcoal, ImpactWestern, Humor Sans, fantasy
font.monospace : Bitstream Vera Sans Mono, DejaVu Sans Mono, Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace
font.monospace : DejaVu Sans Mono, Andale Mono, Nimbus Mono L, Courier New, Courier, Fixed, Terminal, monospace

### TEXT
# text properties used by text.Text. See
Expand Down
55 changes: 40 additions & 15 deletions lib/matplotlib/testing/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from matplotlib import ticker
from matplotlib import pyplot as plt
from matplotlib import ft2font
from matplotlib import rcParams
from matplotlib.testing.noseclasses import KnownFailureTest, \
KnownFailureDidNotFailTest, ImageComparisonFailure
from matplotlib.testing.compare import comparable_formats, compare_images, \
Expand Down Expand Up @@ -109,18 +110,44 @@ def tearDownClass(cls):
cls.original_settings)


def cleanup(func):
@functools.wraps(func)
def wrapped_function(*args, **kwargs):
original_units_registry = matplotlib.units.registry.copy()
original_settings = mpl.rcParams.copy()
try:
func(*args, **kwargs)
finally:
_do_cleanup(original_units_registry,
original_settings)
def cleanup(style=None):
"""
A decorator to ensure that any global state is reset before
running a test.

Parameters
----------
style : str, optional
The name of the style to apply.
"""

return wrapped_function
# If cleanup is used without arguments, `style` will be a
# callable, and we pass it directly to the wrapper generator. If
# cleanup if called with an argument, it is a string naming a
# style, and the function will be passed as an argument to what we
# return. This is a confusing, but somewhat standard, pattern for
# writing a decorator with optional arguments.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Very clear and helpful.


def make_cleanup(func):
@functools.wraps(func)
def wrapped_function(*args, **kwargs):
original_units_registry = matplotlib.units.registry.copy()
original_settings = mpl.rcParams.copy()
matplotlib.style.use(style)
try:
func(*args, **kwargs)
finally:
_do_cleanup(original_units_registry,
original_settings)

return wrapped_function

if isinstance(style, six.string_types):
return make_cleanup
else:
result = make_cleanup(style)
style = 'classic'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't this backwards?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, nevermind... I got mixed up

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The idea here is to keep @cleanup without arguments working. If you pass it no arguments, the first argument should be a function and we want to use classic mode by default. If you pass a string it specifies a style, and the function will be passed in later (through function chaining). This is just typical decorator madness, but I can add a comment if you think it would help.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make a comment here explaining that style in some cases isn't really a style name?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a comment.

return result


def check_freetype_version(ver):
Expand All @@ -138,6 +165,7 @@ def check_freetype_version(ver):
class ImageComparisonTest(CleanupTest):
@classmethod
def setup_class(cls):
CleanupTest.setup_class()
cls._initial_settings = mpl.rcParams.copy()
try:
matplotlib.style.use(cls._style)
Expand All @@ -146,11 +174,8 @@ def setup_class(cls):
mpl.rcParams.clear()
mpl.rcParams.update(cls._initial_settings)
raise
# Because the setup of a CleanupTest might involve
# modifying a few rcparams, this setup should come
# last prior to running the image test.
CleanupTest.setup_class()
cls.original_settings = cls._initial_settings
matplotlib.tests.set_font_settings_for_testing()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this solution to this problem. I got so tripped up by this when I was working on the classic mode PR.

cls._func()

@classmethod
Expand Down
11 changes: 8 additions & 3 deletions lib/matplotlib/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
'test data.')


def set_font_settings_for_testing():
rcParams['font.family'] = 'DejaVu Sans'
rcParams['text.hinting'] = False
rcParams['text.hinting_factor'] = 8


def setup():
# The baseline images are created in this locale, so we should use
# it during all of the tests.
Expand All @@ -45,9 +51,8 @@ def setup():
# tests and are not necessarily the default values as specified in
# rcsetup.py
rcdefaults() # Start with all defaults
rcParams['font.family'] = 'DejaVu Sans'
rcParams['text.hinting'] = False
rcParams['text.hinting_factor'] = 8

set_font_settings_for_testing()


def assert_str_equal(reference_str, test_str,
Expand Down
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/symlog.pdf
Binary file not shown.
Binary file modified lib/matplotlib/tests/baseline_images/test_axes/symlog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading