From d5a5823be7cc65ee62ef60e3108cc7ac067df196 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 29 Sep 2022 02:28:23 -0400 Subject: [PATCH 1/4] Revert "Merge pull request #22361 from anntzer/datetex" This reverts commit c98411e9a8775f3cf409f218503aef68d1f268f8, reversing changes made to ccf5115389dae83898b835c13a8ac59a07514a37. --- lib/matplotlib/dates.py | 12 ++++++++- lib/matplotlib/tests/test_dates.py | 40 ++++++++++++++++-------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py index ac1a7d03c687..672ea2c3b003 100644 --- a/lib/matplotlib/dates.py +++ b/lib/matplotlib/dates.py @@ -173,6 +173,7 @@ import functools import logging import math +import re from dateutil.rrule import (rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, @@ -597,7 +598,16 @@ def drange(dstart, dend, delta): def _wrap_in_tex(text): - return r"{\fontfamily{\familydefault}\selectfont " + text + "}" + p = r'([a-zA-Z]+)' + ret_text = re.sub(p, r'}$\1$\\mathdefault{', text) + + # Braces ensure symbols are not spaced like binary operators. + ret_text = ret_text.replace('-', '{-}').replace(':', '{:}') + # To not concatenate space between numbers. + ret_text = ret_text.replace(' ', r'\;') + ret_text = '$\\mathdefault{' + ret_text + '}$' + ret_text = ret_text.replace('$\\mathdefault{}$', '') + return ret_text ## date tickers and formatters ### diff --git a/lib/matplotlib/tests/test_dates.py b/lib/matplotlib/tests/test_dates.py index 57a131cec4a0..fc5eed7f2856 100644 --- a/lib/matplotlib/tests/test_dates.py +++ b/lib/matplotlib/tests/test_dates.py @@ -322,13 +322,13 @@ def callable_formatting_function(dates, _): @pytest.mark.parametrize('delta, expected', [ (datetime.timedelta(weeks=52 * 200), - range(1990, 2171, 20)), + [r'$\mathdefault{%d}$' % year for year in range(1990, 2171, 20)]), (datetime.timedelta(days=30), - ['1990-01-%02d' % day for day in range(1, 32, 3)]), + [r'$\mathdefault{1990{-}01{-}%02d}$' % day for day in range(1, 32, 3)]), (datetime.timedelta(hours=20), - ['01-01 %02d' % hour for hour in range(0, 21, 2)]), + [r'$\mathdefault{01{-}01\;%02d}$' % hour for hour in range(0, 21, 2)]), (datetime.timedelta(minutes=10), - ['01 00:%02d' % minu for minu in range(0, 11)]), + [r'$\mathdefault{01\;00{:}%02d}$' % minu for minu in range(0, 11)]), ]) def test_date_formatter_usetex(delta, expected): style.use("default") @@ -341,8 +341,7 @@ def test_date_formatter_usetex(delta, expected): locator.axis.set_view_interval(mdates.date2num(d1), mdates.date2num(d2)) formatter = mdates.AutoDateFormatter(locator, usetex=True) - assert [formatter(loc) for loc in locator()] == [ - r'{\fontfamily{\familydefault}\selectfont %s}' % s for s in expected] + assert [formatter(loc) for loc in locator()] == expected def test_drange(): @@ -645,14 +644,24 @@ def test_offset_changes(): @pytest.mark.parametrize('t_delta, expected', [ (datetime.timedelta(weeks=52 * 200), - range(1980, 2201, 20)), + ['$\\mathdefault{%d}$' % (t, ) for t in range(1980, 2201, 20)]), (datetime.timedelta(days=40), - ['Jan', '05', '09', '13', '17', '21', '25', '29', 'Feb', '05', '09']), + ['Jan', '$\\mathdefault{05}$', '$\\mathdefault{09}$', + '$\\mathdefault{13}$', '$\\mathdefault{17}$', '$\\mathdefault{21}$', + '$\\mathdefault{25}$', '$\\mathdefault{29}$', 'Feb', + '$\\mathdefault{05}$', '$\\mathdefault{09}$']), (datetime.timedelta(hours=40), - ['Jan-01', '04:00', '08:00', '12:00', '16:00', '20:00', - 'Jan-02', '04:00', '08:00', '12:00', '16:00']), + ['Jan$\\mathdefault{{-}01}$', '$\\mathdefault{04{:}00}$', + '$\\mathdefault{08{:}00}$', '$\\mathdefault{12{:}00}$', + '$\\mathdefault{16{:}00}$', '$\\mathdefault{20{:}00}$', + 'Jan$\\mathdefault{{-}02}$', '$\\mathdefault{04{:}00}$', + '$\\mathdefault{08{:}00}$', '$\\mathdefault{12{:}00}$', + '$\\mathdefault{16{:}00}$']), (datetime.timedelta(seconds=2), - ['59.5', '00:00', '00.5', '01.0', '01.5', '02.0', '02.5']), + ['$\\mathdefault{59.5}$', '$\\mathdefault{00{:}00}$', + '$\\mathdefault{00.5}$', '$\\mathdefault{01.0}$', + '$\\mathdefault{01.5}$', '$\\mathdefault{02.0}$', + '$\\mathdefault{02.5}$']), ]) def test_concise_formatter_usetex(t_delta, expected): d1 = datetime.datetime(1997, 1, 1) @@ -663,8 +672,7 @@ def test_concise_formatter_usetex(t_delta, expected): locator.axis.set_view_interval(mdates.date2num(d1), mdates.date2num(d2)) formatter = mdates.ConciseDateFormatter(locator, usetex=True) - assert formatter.format_ticks(locator()) == [ - r'{\fontfamily{\familydefault}\selectfont %s}' % s for s in expected] + assert formatter.format_ticks(locator()) == expected def test_concise_formatter_formats(): @@ -1347,12 +1355,6 @@ def test_date_ticker_factory(span, expected_locator): assert isinstance(locator, expected_locator) -def test_usetex_newline(): - fig, ax = plt.subplots() - ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m\n%Y')) - fig.canvas.draw() - - def test_datetime_masked(): # make sure that all-masked data falls back to the viewlim # set in convert.axisinfo.... From 25d23e904754c67df032aff1cb23dee5655e86ff Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 29 Sep 2022 02:54:26 -0400 Subject: [PATCH 2/4] Revert "Let TeX handle newlines itself." This reverts commit 157b0bed5349d0ec56c3d8bfcb12a3c1a5052cf1. --- lib/matplotlib/tests/test_text.py | 21 ++++++++++++++++++--- lib/matplotlib/texmanager.py | 2 +- lib/matplotlib/text.py | 3 +-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/tests/test_text.py b/lib/matplotlib/tests/test_text.py index b5c1bbff641b..9b3f70526763 100644 --- a/lib/matplotlib/tests/test_text.py +++ b/lib/matplotlib/tests/test_text.py @@ -806,11 +806,26 @@ def test_metrics_cache(): fig = plt.figure() fig.text(.3, .5, "foo\nbar") - fig.text(.5, .5, "foo\nbar") fig.text(.3, .5, "foo\nbar", usetex=True) fig.text(.5, .5, "foo\nbar", usetex=True) fig.canvas.draw() + renderer = fig._get_renderer() + ys = {} # mapping of strings to where they were drawn in y with draw_tex. + + def call(*args, **kwargs): + renderer, x, y, s, *_ = args + ys.setdefault(s, set()).add(y) + + renderer.draw_tex = call + fig.canvas.draw() + assert [*ys] == ["foo", "bar"] + # Check that both TeX strings were drawn with the same y-position for both + # single-line substrings. Previously, there used to be an incorrect cache + # collision with the non-TeX string (drawn first here) whose metrics would + # get incorrectly reused by the first TeX string. + assert len(ys["foo"]) == len(ys["bar"]) == 1 info = mpl.text._get_text_metrics_with_cache_impl.cache_info() - # Each string gets drawn twice, so the second draw results in a hit. - assert info.hits == info.misses + # Every string gets a miss for the first layouting (extents), then a hit + # when drawing, but "foo\nbar" gets two hits as it's drawn twice. + assert info.hits > info.misses diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index c0d37edbc3d8..bbf0a4cf5ab3 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -230,7 +230,7 @@ def _get_tex_source(cls, tex, fontsize): r"% last line's baseline.", rf"\fontsize{{{fontsize}}}{{{baselineskip}}}%", r"\ifdefined\psfrag\else\hbox{}\fi%", - rf"{{\obeylines{fontcmd} {tex}}}%", + rf"{{{fontcmd} {tex}}}%", r"\special{matplotlibbaselinemarker}%", r"\end{document}", ]) diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py index 356bdb36a8c0..abd5cb959839 100644 --- a/lib/matplotlib/text.py +++ b/lib/matplotlib/text.py @@ -334,8 +334,7 @@ def _get_layout(self, renderer): of a rotated text when necessary. """ thisx, thisy = 0.0, 0.0 - text = self.get_text() - lines = [text] if self.get_usetex() else text.split("\n") # Not empty. + lines = self.get_text().split("\n") # Ensures lines is not empty. ws = [] hs = [] From bcd823266abf398f780c04b365e873c5ce58fe56 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 29 Sep 2022 03:00:15 -0400 Subject: [PATCH 3/4] Revert "Switch TeX baseline detection to use a dvi special." This reverts commit c973552b49d6d6c583a52d1ac838bc0748462666. --- lib/matplotlib/dviread.py | 32 ++++++++++++++++++++++++++++++-- lib/matplotlib/texmanager.py | 1 - 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/dviread.py b/lib/matplotlib/dviread.py index 8c83d8d6c508..296e67c4d5ff 100644 --- a/lib/matplotlib/dviread.py +++ b/lib/matplotlib/dviread.py @@ -352,10 +352,40 @@ def _read(self): Read one page from the file. Return True if successful, False if there were no more pages. """ + # Pages appear to start with the sequence + # bop (begin of page) + # xxx comment + # # if using chemformula + # down + # push + # down + # # if using xcolor + # down + # push + # down (possibly multiple) + # push <= here, v is the baseline position. + # etc. + # (dviasm is useful to explore this structure.) + # Thus, we use the vertical position at the first time the stack depth + # reaches 3, while at least three "downs" have been executed (excluding + # those popped out (corresponding to the chemformula preamble)), as the + # baseline (the "down" count is necessary to handle xcolor). + down_stack = [0] self._baseline_v = None while True: byte = self.file.read(1)[0] self._dtable[byte](self, byte) + name = self._dtable[byte].__name__ + if name == "_push": + down_stack.append(down_stack[-1]) + elif name == "_pop": + down_stack.pop() + elif name == "_down": + down_stack[-1] += 1 + if (self._baseline_v is None + and len(getattr(self, "stack", [])) == 3 + and down_stack[-1] >= 4): + self._baseline_v = self.v if byte == 140: # end of page return True if self.state is _dvistate.post_post: # end of file @@ -488,8 +518,6 @@ def _fnt_num(self, new_f): @_dispatch(min=239, max=242, args=('ulen1',)) def _xxx(self, datalen): special = self.file.read(datalen) - if special == b'matplotlibbaselinemarker': - self._baseline_v = self.v _log.debug( 'Dvi._xxx: encountered special: %s', ''.join([chr(ch) if 32 <= ch < 127 else '<%02x>' % ch diff --git a/lib/matplotlib/texmanager.py b/lib/matplotlib/texmanager.py index bbf0a4cf5ab3..e3b500f948bc 100644 --- a/lib/matplotlib/texmanager.py +++ b/lib/matplotlib/texmanager.py @@ -231,7 +231,6 @@ def _get_tex_source(cls, tex, fontsize): rf"\fontsize{{{fontsize}}}{{{baselineskip}}}%", r"\ifdefined\psfrag\else\hbox{}\fi%", rf"{{{fontcmd} {tex}}}%", - r"\special{matplotlibbaselinemarker}%", r"\end{document}", ]) From 4f8e20f80482f430c10fb9121124ae24421f824c Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Thu, 29 Sep 2022 23:48:51 -0400 Subject: [PATCH 4/4] Add a test for multiline text with usetex --- .../baseline_images/test_usetex/eqnarray.png | Bin 0 -> 1322 bytes lib/matplotlib/tests/test_usetex.py | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png diff --git a/lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png b/lib/matplotlib/tests/baseline_images/test_usetex/eqnarray.png new file mode 100644 index 0000000000000000000000000000000000000000..249f15d238ddacf216965801675667d6edb85da3 GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0vp^DImv~(l@_;SZF8i$S^J$mm}g-zS*UD3z4Tw8JdHArUurkeZhk1ec^Up8?SV6on+(UlN+ZFyYP4w^=jzVwKBY? zT>pOjC>S~I;nSzAd*jx>D(mA~I^kyx-&)gOf9-E|{rE$bd8wwe zeRZav{$K0CXVEAa)UtYN5XWJG$Z2oqOisO-pFNv#XaBk6#yAfFmJK@GQQ2E==lZBk zUMsyTLZ_gp&65Y~Jgof^CXZf+YHnhsK<8yukgjR(|ot6?ddpUVjaY zRfcQT&*nXU`0N?mfhrNn$f^@@*Q5 zmb~FUv(ZV{C428wBb{w!)qCS457p_PE}XOW|E62&Qzf$$-z(3be3E7JO`fe$yxVf$ zpJ2LX9+w>}XTS6!cXSIyry4Q;? zzYJI}J^KQ;rTL2GYl>Y6r2GK(r{{E4*ykMJuv|Vt#zF7N9jBrLoNwCa1bgr)$SdCG zJ(>G&-r3qR&QrA$-?u$!_-gh(!QjBtr>c`w93|S0@9VLD{Nw#@%Q+7Vc6|M|{r2tK ze;z(mJpcLY>S;2^HM0w4-q#jixP3eN=jWoGcYdAW_{;G#%VXVwi0Up8<=;^*+D~>X z?)2^2V7i;9A>zb+j+2bplCzbY|As!@;`GnWLyyNfW9{kWM2Ts^a@tq!JMR;obb1qy zqrigOZ<9=<60PPYna#dv-?UJysPBSb pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy