Source code for toyplot.text

# Copyright 2014, Sandia Corporation. Under the terms of Contract
# DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain
# rights in this software.

"""Functions for manipulating text."""

from __future__ import division

import numpy
import toyplot.broadcast
import toyplot.require
import toyplot.transform
import toyplot.units


[docs]def extents(text, angle, style): """Compute (inexact) extents for a text string, based on the given coordinates and style. """ text = toyplot.require.string_vector(text) lengths = numpy.array([len(string) for string in text]) font_size = toyplot.units.convert(style["font-size"], target="px") anchor_shift = toyplot.units.convert( style.get( "-toyplot-anchor-shift", "0px"), target="px", reference=font_size) text_anchor = style["text-anchor"] baseline_shift = toyplot.units.convert( style.get("baseline-shift", "0px"), target="px", reference=font_size) alignment_baseline = style["alignment-baseline"] x = toyplot.broadcast.scalar(anchor_shift, text.shape) y = toyplot.broadcast.scalar(-baseline_shift, text.shape) # Because we don't have any metrics for the font, assume that the average # character width and height match the font size. width = font_size * lengths height = font_size # Compute left/right extents relative to the text anchor. if text_anchor == "start": left = x right = x + width elif text_anchor == "middle": left = x - width / 2 right = x + width / 2 elif text_anchor == "end": left = x - width right = x else: raise ValueError("Unknown text-anchor value: %s" % text_anchor) # Compute top/bottom extents relative to the text baseline. if alignment_baseline == "hanging": top = y bottom = y + height elif alignment_baseline == "middle" or alignment_baseline == "central": top = y - height / 2 bottom = y + height / 2 elif alignment_baseline == "alphabetic": top = y - height bottom = y else: raise ValueError( "Unknown alignment-baseline value: %s" % alignment_baseline) # Compute axis-aligned extents regardless of the text rotation angle. corner1 = numpy.column_stack((left, -top)) corner2 = numpy.column_stack((right, -top)) corner3 = numpy.column_stack((right, -bottom)) corner4 = numpy.column_stack((left, -bottom)) for index, theta in enumerate(angle): transformation = toyplot.transform.rotation(theta) corner1[index] = corner1[index] * transformation corner2[index] = corner2[index] * transformation corner3[index] = corner3[index] * transformation corner4[index] = corner4[index] * transformation left = numpy.minimum(corner1.T[0], numpy.minimum( corner2.T[0], numpy.minimum(corner3.T[0], corner4.T[0]))) right = numpy.maximum(corner1.T[0], numpy.maximum( corner2.T[0], numpy.maximum(corner3.T[0], corner4.T[0]))) top = -numpy.maximum(corner1.T[1], numpy.maximum(corner2.T[1], numpy.maximum(corner3.T[1], corner4.T[1]))) bottom = - \ numpy.minimum(corner1.T[1], numpy.minimum( corner2.T[1], numpy.minimum(corner3.T[1], corner4.T[1]))) return (left, right, top, bottom)