{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Using a text as a Path\n\n`~matplotlib.text.TextPath` creates a `.Path` that is the outline of the\ncharacters of a text. The resulting path can be employed e.g. as a clip path\nfor an image.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import 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,\n 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 = plt.imread(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=plt.cm.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.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }