matplotlib 3.5.1

>>> r"""
=================
Custom box styles
=================

This example demonstrates the implementation of a custom `.BoxStyle`.
Custom `.ConnectionStyle`\s and `.ArrowStyle`\s can be similarly defined.
"""
... 
... from matplotlib.patches import BoxStyle
... from matplotlib.path import Path
... import matplotlib.pyplot as plt
... 
... 
... ###############################################################################
... # Custom box styles can be implemented as a function that takes arguments
... # specifying both a rectangular box and the amount of "mutation", and
... # returns the "mutated" path. The specific signature is the one of
... # ``custom_box_style`` below.
... #
... # Here, we return a new path which adds an "arrow" shape on the left of the
... # box.
... #
... # The custom box style can then be used by passing
... # ``bbox=dict(boxstyle=custom_box_style, ...)`` to `.Axes.text`.
... 
... 
... def custom_box_style(x0, y0, width, height, mutation_size):
...  """ Given the location and size of the box, return the path of the box around it. Rotation is automatically taken care of. Parameters ---------- x0, y0, width, height : float Box location and size. mutation_size : float Mutation reference scale, typically the text font size. """
...  # padding
...  mypad = 0.3
...  pad = mutation_size * mypad
...  # width and height with padding added.
...  width = width + 2 * pad
...  height = height + 2 * pad
...  # boundary of the padded box
...  x0, y0 = x0 - pad, y0 - pad
...  x1, y1 = x0 + width, y0 + height
...  # return the new path
...  return Path([(x0, y0),
...  (x1, y0), (x1, y1), (x0, y1),
...  (x0-pad, (y0+y1)/2), (x0, y0),
...  (x0, y0)],
...  closed=True)
... 
... 
... fig, ax = plt.subplots(figsize=(3, 3))
... ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", rotation=30,
...  bbox=dict(boxstyle=custom_box_style, alpha=0.2))
... 
... 
... ###############################################################################
... # Likewise, custom box styles can be implemented as classes that implement
... # ``__call__``.
... #
... # The classes can then be registered into the ``BoxStyle._style_list`` dict,
... # which allows specifying the box style as a string,
... # ``bbox=dict(boxstyle="registered_name,param=value,...", ...)``.
... # Note that this registration relies on internal APIs and is therefore not
... # officially supported.
... 
... 
... class MyStyle:
...  """A simple box."""
... 
...  def __init__(self, pad=0.3):
...  """ The arguments must be floats and have default values. Parameters ---------- pad : float amount of padding """
...  self.pad = pad
...  super().__init__()
... 
...  def __call__(self, x0, y0, width, height, mutation_size):
...  """ Given the location and size of the box, return the path of the box around it. Rotation is automatically taken care of. Parameters ---------- x0, y0, width, height : float Box location and size. mutation_size : float Reference scale for the mutation, typically the text font size. """
...  # padding
...  pad = mutation_size * self.pad
...  # width and height with padding added
...  width = width + 2.*pad
...  height = height + 2.*pad
...  # boundary of the padded box
...  x0, y0 = x0 - pad, y0 - pad
...  x1, y1 = x0 + width, y0 + height
...  # return the new path
...  return Path([(x0, y0),
...  (x1, y0), (x1, y1), (x0, y1),
...  (x0-pad, (y0+y1)/2.), (x0, y0),
...  (x0, y0)],
...  closed=True)
... 
... 
... BoxStyle._style_list["angled"] = MyStyle # Register the custom style.
... 
... fig, ax = plt.subplots(figsize=(3, 3))
... ax.text(0.5, 0.5, "Test", size=30, va="center", ha="center", rotation=30,
...  bbox=dict(boxstyle="angled,pad=0.5", alpha=0.2))
... 
... del BoxStyle._style_list["angled"] # Unregister it.
... 
... plt.show()
...