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

Skip to content

Rev coord wrapping #4843

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
Aug 6, 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
9 changes: 9 additions & 0 deletions doc/api/api_changes/2015-07-30_annotation_wrap.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
No annotation coordinates wrap
``````````````````````````````

In #2351 for 1.4.0 the behavior of ['axes points', 'axes pixel',
'figure points', 'figure pixel'] as coordinates was change to
no longer wrap for negative values. In 1.4.3 this change was
reverted for 'axes points' and 'axes pixel' and in addition caused
'axes fraction' to wrap. For 1.5 the behavior has been reverted to
as it was in 1.4.0-1.4.2, no wrapping for any type of coordinate.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
216 changes: 53 additions & 163 deletions lib/matplotlib/tests/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,169 +313,59 @@ def test_bbox_clipping():
t.set_bbox({"boxstyle": "round, pad=0.1"})


@image_comparison(baseline_images=['annotation_negative_coords'],
@image_comparison(baseline_images=['annotation_negative_ax_coords'],
extensions=['png'])
def test_annotation_negative_coords():
fig = plt.figure()
ax = plt.subplot(1, 1, 1)

ax.annotate("+fpt", (15, 40), xycoords="figure points")
ax.annotate("+fpx", (25, 30), xycoords="figure pixels")
ax.annotate("+apt", (35, 20), xycoords="axes points")
ax.annotate("+apx", (45, 10), xycoords="axes pixels")

ax.annotate("-fpt", (-55, -40), xycoords="figure points")
ax.annotate("-fpx", (-45, -30), xycoords="figure pixels")
ax.annotate("-apt", (-35, -20), xycoords="axes points")
ax.annotate("-apx", (-25, -10), xycoords="axes pixels")


@cleanup
def test_text_annotation_get_window_extent():
figure = Figure(dpi=100)
renderer = RendererAgg(200, 200, 100)

# Only text annotation
annotation = Annotation('test', xy=(0, 0))
annotation.set_figure(figure)

text = Text(text='test', x=0, y=0)
text.set_figure(figure)

bbox = annotation.get_window_extent(renderer=renderer)

text_bbox = text.get_window_extent(renderer=renderer)
eq_(bbox.width, text_bbox.width)
eq_(bbox.height, text_bbox.height)

_, _, d = renderer.get_text_width_height_descent(
'text', annotation._fontproperties, ismath=False)
_, _, lp_d = renderer.get_text_width_height_descent(
'lp', annotation._fontproperties, ismath=False)
below_line = max(d, lp_d)

# These numbers are specific to the current implementation of Text
points = bbox.get_points()
eq_(points[0, 0], 0.0)
eq_(points[1, 0], text_bbox.width)
eq_(points[0, 1], -below_line)
eq_(points[1, 1], text_bbox.height - below_line)


@cleanup
def test_text_with_arrow_annotation_get_window_extent():
headwidth = 21
fig, ax = plt.subplots(dpi=100)
txt = ax.text(s='test', x=0, y=0)
ann = ax.annotate(
'test',
xy=(0.0, 50.0),
xytext=(50.0, 50.0), xycoords='figure pixels',
arrowprops={
'facecolor': 'black', 'width': 2,
'headwidth': headwidth, 'shrink': 0.0})

plt.draw()
renderer = fig.canvas.renderer
# bounding box of text
text_bbox = txt.get_window_extent(renderer=renderer)
# bounding box of annotation (text + arrow)
bbox = ann.get_window_extent(renderer=renderer)
# bounding box of arrow
arrow_bbox = ann.arrow_patch.get_window_extent(renderer)
# bounding box of annotation text
ann_txt_bbox = Text.get_window_extent(ann)

# make sure annotation width is 50 px wider than
# just the text
eq_(bbox.width, text_bbox.width + 50.0)
# make sure the annotation text bounding box is same size
# as the bounding box of the same string as a Text object
eq_(ann_txt_bbox.height, text_bbox.height)
eq_(ann_txt_bbox.width, text_bbox.width)
# compute the expected bounding box of arrow + text
expected_bbox = Bbox.union([ann_txt_bbox, arrow_bbox])
assert_almost_equal(bbox.height, expected_bbox.height)


@cleanup
def test_arrow_annotation_get_window_extent():
dpi = 100
dots_per_point = dpi / 72
figure = Figure(dpi=dpi)
figure.set_figwidth(2.0)
figure.set_figheight(2.0)
renderer = RendererAgg(200, 200, 100)

# Text annotation with arrow; arrow dimensions are in points
annotation = Annotation(
'', xy=(0.0, 50.0), xytext=(50.0, 50.0), xycoords='figure pixels',
arrowprops={
'facecolor': 'black', 'width': 8, 'headwidth': 10, 'shrink': 0.0})
annotation.set_figure(figure)
annotation.draw(renderer)

bbox = annotation.get_window_extent()
points = bbox.get_points()

eq_(bbox.width, 50.0)
assert_almost_equal(bbox.height, 10.0 * dots_per_point)
eq_(points[0, 0], 0.0)
eq_(points[0, 1], 50.0 - 5 * dots_per_point)


@cleanup
def test_empty_annotation_get_window_extent():
figure = Figure(dpi=100)
figure.set_figwidth(2.0)
figure.set_figheight(2.0)
renderer = RendererAgg(200, 200, 100)

# Text annotation with arrow
annotation = Annotation(
'', xy=(0.0, 50.0), xytext=(0.0, 50.0), xycoords='figure pixels')
annotation.set_figure(figure)
annotation.draw(renderer)

bbox = annotation.get_window_extent()
points = bbox.get_points()

eq_(points[0, 0], 0.0)
eq_(points[1, 0], 0.0)
eq_(points[1, 1], 50.0)
eq_(points[0, 1], 50.0)

def test_annotation_negative_ax_coords():
fig, ax = plt.subplots()

@image_comparison(baseline_images=['basictext_wrap'],
extensions=['png'])
def test_basic_wrap():
fig = plt.figure()
plt.axis([0, 10, 0, 10])
t = "This is a really long string that I'd rather have wrapped so that" \
" it doesn't go outside of the figure, but if it's long enough it" \
" will go off the top or bottom!"
plt.text(4, 1, t, ha='left', rotation=15, wrap=True)
plt.text(6, 5, t, ha='left', rotation=15, wrap=True)
plt.text(5, 5, t, ha='right', rotation=-15, wrap=True)
plt.text(5, 10, t, fontsize=18, style='oblique', ha='center',
va='top', wrap=True)
plt.text(3, 4, t, family='serif', style='italic', ha='right', wrap=True)
plt.text(-1, 0, t, ha='left', rotation=-15, wrap=True)


@image_comparison(baseline_images=['fonttext_wrap'],
ax.annotate('+ pts',
xytext=[30, 20], textcoords='axes points',
xy=[30, 20], xycoords='axes points', fontsize=32)
ax.annotate('- pts',
xytext=[30, -20], textcoords='axes points',
xy=[30, -20], xycoords='axes points', fontsize=32,
va='top')
ax.annotate('+ frac',
xytext=[0.75, 0.05], textcoords='axes fraction',
xy=[0.75, 0.05], xycoords='axes fraction', fontsize=32)
ax.annotate('- frac',
xytext=[0.75, -0.05], textcoords='axes fraction',
xy=[0.75, -0.05], xycoords='axes fraction', fontsize=32,
va='top')

ax.annotate('+ pixels',
xytext=[160, 25], textcoords='axes pixels',
xy=[160, 25], xycoords='axes pixels', fontsize=32)
ax.annotate('- pixels',
xytext=[160, -25], textcoords='axes pixels',
xy=[160, -25], xycoords='axes pixels', fontsize=32,
va='top')


@image_comparison(baseline_images=['annotation_negative_fig_coords'],
extensions=['png'])
def test_font_wrap():
fig = plt.figure()
plt.axis([0, 10, 0, 10])
t = "This is a really long string that I'd rather have wrapped so that" \
" it doesn't go outside of the figure, but if it's long enough it" \
" will go off the top or bottom!"
plt.text(4, -1, t, fontsize=18, family='serif', ha='left', rotation=15,
wrap=True)
plt.text(6, 5, t, family='sans serif', ha='left', rotation=15, wrap=True)
plt.text(5, 5, t, weight='light', ha='right', rotation=-15, wrap=True)
plt.text(5, 10, t, weight='heavy', ha='center', va='top', wrap=True)
plt.text(3, 4, t, family='monospace', ha='right', wrap=True)
plt.text(-1, 0, t, fontsize=14, style='italic', ha='left', rotation=-15,
wrap=True)
def test_annotation_negative_fig_coords():
Copy link
Member

Choose a reason for hiding this comment

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

Note: I'd love to get to the point where we used graphics contexts for testing some of this stuff, rather than images.

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you mean by graphics contexts in this context?

Copy link
Member

Choose a reason for hiding this comment

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

The GraphicsContextBase and we simply check that the appropriate attributes are set at draw time.

It is another test completely to ensure that a backend is producing the appropriate pixels for a GraphicsContextBase, IMHO.

fig, ax = plt.subplots()

ax.annotate('+ pts',
xytext=[10, 120], textcoords='figure points',
xy=[10, 120], xycoords='figure points', fontsize=32)
ax.annotate('- pts',
xytext=[-10, 180], textcoords='figure points',
xy=[-10, 180], xycoords='figure points', fontsize=32,
va='top')
ax.annotate('+ frac',
xytext=[0.05, 0.55], textcoords='figure fraction',
xy=[0.05, 0.55], xycoords='figure fraction', fontsize=32)
ax.annotate('- frac',
xytext=[-0.05, 0.5], textcoords='figure fraction',
xy=[-0.05, 0.5], xycoords='figure fraction', fontsize=32,
va='top')

ax.annotate('+ pixels',
xytext=[50, 50], textcoords='figure pixels',
xy=[50, 50], xycoords='figure pixels', fontsize=32)
ax.annotate('- pixels',
xytext=[-50, 100], textcoords='figure pixels',
xy=[-50, 100], xycoords='figure pixels', fontsize=32,
va='top')
23 changes: 6 additions & 17 deletions lib/matplotlib/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -1704,17 +1704,17 @@ def _get_xy(self, renderer, x, y, s):
if s2 == 'data':
y = float(self.convert_yunits(y))

tr = self._get_xy_transform(renderer, (x, y), s)
tr = self._get_xy_transform(renderer, s)
x1, y1 = tr.transform_point((x, y))
return x1, y1

def _get_xy_transform(self, renderer, xy, s):
def _get_xy_transform(self, renderer, s):

if isinstance(s, tuple):
s1, s2 = s
from matplotlib.transforms import blended_transform_factory
tr1 = self._get_xy_transform(renderer, xy, s1)
tr2 = self._get_xy_transform(renderer, xy, s2)
tr1 = self._get_xy_transform(renderer, s1)
tr2 = self._get_xy_transform(renderer, s2)
tr = blended_transform_factory(tr1, tr2)
return tr

Expand Down Expand Up @@ -1763,17 +1763,7 @@ def _get_xy_transform(self, renderer, xy, s):
# bbox0 = self._get_bbox(renderer, bbox)

if bbox0 is not None:
x, y = xy
bounds = bbox0.extents
if x < 0:
x0 = bounds[2]
else:
x0 = bounds[0]
if y < 0:
y0 = bounds[3]
else:
y0 = bounds[1]
xy0 = (x0, y0)
xy0 = bbox0.bounds[:2]
elif bbox_name == "offset":
xy0 = self._get_ref_xy(renderer)

Expand Down Expand Up @@ -2120,8 +2110,7 @@ def _update_position_xytext(self, renderer, xy_pixel):
patch.
"""
# generate transformation,
self.set_transform(self._get_xy_transform(
renderer, self.xy, self.anncoords))
self.set_transform(self._get_xy_transform(renderer, self.anncoords))

ox0, oy0 = self._get_xy_display()
ox1, oy1 = xy_pixel
Expand Down