{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Using a text as a Path\n\n`.TextPath` creates a `.Path` that is the outline of the characters of a text.\nThe resulting path can be employed e.g. as a clip path for an image.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from PIL import Image\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib.cbook import get_sample_data\nfrom matplotlib.image import BboxImage\nfrom matplotlib.offsetbox import AnchoredOffsetbox, AnnotationBbox, AuxTransformBox\nfrom matplotlib.patches import PathPatch, Shadow\nfrom matplotlib.text import TextPath\nfrom matplotlib.transforms import IdentityTransform\n\n\nclass PathClippedImagePatch(PathPatch):\n    \"\"\"\n    The given image is used to draw the face of the patch. Internally,\n    it uses BboxImage whose clippath set to the path of the patch.\n\n    FIXME : The result is currently dpi dependent.\n    \"\"\"\n\n    def __init__(self, path, bbox_image, **kwargs):\n        super().__init__(path, **kwargs)\n        self.bbox_image = BboxImage(\n            self.get_window_extent, norm=None, origin=None)\n        self.bbox_image.set_data(bbox_image)\n\n    def set_facecolor(self, color):\n        \"\"\"Simply ignore facecolor.\"\"\"\n        super().set_facecolor(\"none\")\n\n    def draw(self, renderer=None):\n        # the clip path must be updated every draw. any solution? -JJ\n        self.bbox_image.set_clip_path(self._path, self.get_transform())\n        self.bbox_image.draw(renderer)\n        super().draw(renderer)\n\n\nif __name__ == \"__main__\":\n\n    fig, (ax1, ax2) = plt.subplots(2)\n\n    # EXAMPLE 1\n\n    arr = Image.open(get_sample_data(\"grace_hopper.jpg\"))\n\n    text_path = TextPath((0, 0), \"!?\", size=150)\n    p = PathClippedImagePatch(text_path, arr, ec=\"k\")\n\n    # make offset box\n    offsetbox = AuxTransformBox(IdentityTransform())\n    offsetbox.add_artist(p)\n\n    # make anchored offset box\n    ao = AnchoredOffsetbox(loc='upper left', child=offsetbox, frameon=True,\n                           borderpad=0.2)\n    ax1.add_artist(ao)\n\n    # another text\n    for usetex, ypos, string in [\n            (False, 0.25, r\"textpath supports mathtext\"),\n            (True, 0.05, r\"textpath supports \\TeX\"),\n    ]:\n        text_path = TextPath((0, 0), string, size=20, usetex=usetex)\n\n        p1 = PathPatch(text_path, ec=\"w\", lw=3, fc=\"w\", alpha=0.9)\n        p2 = PathPatch(text_path, ec=\"none\", fc=\"k\")\n\n        offsetbox2 = AuxTransformBox(IdentityTransform())\n        offsetbox2.add_artist(p1)\n        offsetbox2.add_artist(p2)\n\n        ab = AnnotationBbox(offsetbox2, (0.95, ypos),\n                            xycoords='axes fraction',\n                            boxcoords=\"offset points\",\n                            box_alignment=(1., 0.),\n                            frameon=False,\n                            )\n        ax1.add_artist(ab)\n\n    ax1.imshow([[0, 1, 2], [1, 2, 3]], cmap=\"gist_gray_r\",\n               interpolation=\"bilinear\", aspect=\"auto\")\n\n    # EXAMPLE 2\n\n    arr = np.arange(256).reshape(1, 256)\n\n    for usetex, xpos, string in [\n            (False, 0.25,\n             r\"$\\left[\\sum_{n=1}^\\infty\\frac{-e^{i\\pi}}{2^n}\\right]$!\"),\n            (True, 0.75,\n             r\"$\\displaystyle\\left[\\sum_{n=1}^\\infty\"\n             r\"\\frac{-e^{i\\pi}}{2^n}\\right]$!\"),\n    ]:\n        text_path = TextPath((0, 0), string, size=40, usetex=usetex)\n        text_patch = PathClippedImagePatch(text_path, arr, ec=\"none\")\n        shadow1 = Shadow(text_patch, 1, -1, fc=\"none\", ec=\"0.6\", lw=3)\n        shadow2 = Shadow(text_patch, 1, -1, fc=\"0.3\", ec=\"none\")\n\n        # make offset box\n        offsetbox = AuxTransformBox(IdentityTransform())\n        offsetbox.add_artist(shadow1)\n        offsetbox.add_artist(shadow2)\n        offsetbox.add_artist(text_patch)\n\n        # place the anchored offset box using AnnotationBbox\n        ab = AnnotationBbox(offsetbox, (xpos, 0.5), box_alignment=(0.5, 0.5))\n\n        ax2.add_artist(ab)\n\n    ax2.set_xlim(0, 1)\n    ax2.set_ylim(0, 1)\n\n    plt.show()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}