From 63af5a286136c2bbca040c9f40946f65b6648f20 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger Date: Mon, 1 Mar 2021 16:41:37 +0100 Subject: [PATCH 1/2] Add test case to check if kerning is added to pdf --- .../test_text/text_pdf_kerning.pdf | Bin 0 -> 3232 bytes lib/matplotlib/tests/test_text.py | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 lib/matplotlib/tests/baseline_images/test_text/text_pdf_kerning.pdf diff --git a/lib/matplotlib/tests/baseline_images/test_text/text_pdf_kerning.pdf b/lib/matplotlib/tests/baseline_images/test_text/text_pdf_kerning.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7db9a1b44fad530adc4a59230a156a3cbfbca8b4 GIT binary patch literal 3232 zcmb_fYitx%6c&lZOi-&piH#&T!a{24&hySALZ$6?5p1D$Ng*Q9>F(`z>UL(CoytNr zkQjLwNz?=|Dv2>lNFYXps7PW8`U5Nwg8Gji8l%yFB!Ehc#B=WK>`u20A;xV^?##K5 z^PO|PbM7?Jn@YFJNli!`y+V$BDab@3-oUW1Y#9-I?K~?H1vGs`T(`Bzh}dZdcEQV& zwl;yeIb3MQHguJPm6^Z}7}3H_Y0nLa8b0^hLBM>MP<$1{Uf;`RSU@&{om3jmXXSv1 zt46?PM`i4+jH}2dB4&o{oa5$+9&X>Tc3_xg17h&QYjEVa1MRNs1tlU&A%ado!(32U z;TbD^Z?s6z)6NVLQ|v`2%lcM=b$DCn+it07`^?R5jhqkHgDtU#D#3~nrp2q}tt+9^P!h?p)wC{rx!=B{--Vb|^31?O`r2fA7T66ZNllhCMP6$n(%=vguOJd3Cx&1d^Uh=5k zsO!nu=a(M$mXDPio5q|E^DXnDaZSdrywtIye8vv%|}?tCP=M-Tclsk8Lk}wdLxAaILSTe@08Up(Isr$yIdsAbF zzIgC2bH|^1KA8K*t&!cW^RF!beb2SR^SOh&7M}RI@zX=aOn2X!!&_z#e`G9p{I|q~ zf3$Pkl1*+;r?n)h)*q8t1xtH2zdyfoE<4TNmUh( zz$GbG%KA<*@O&ckt`P3*u>;@X^^=q&tXcT0KEc**yJAV90Bems0wqxMOb|1p0|DVOJ|Y$(;O90P|oaoM}~5o!4N#L{#OD z{jG-zJq%i=lWlkN1%`3!vCAAF;L{Z7H31vxN4sIX>p~`Or~-@mfsTchqe~L`A4K@C zXQ;ACG{_%xKw_#U(N$frs6-4?B8owYYDruu;KX@cuj+C*ss^sVoe0sq3TsjDj7X>| zLu4*9oO?2=LUNoz8=RBiiRl!vF#X2&{lMDeU1viNN8=nTD1$e339j2pe6) z5rpRj&4nURaFOrC_|_f(V0eTA9^(w60^|`5qI5+gq)do_a8#NhquU%l@?a8F^of%R z2!*?BuIpi1IUBP!eb4*Ku*Mj^8q;#3Fk_M6Uc|SATIt6XCOBs zLCACKf5eS+iVjSw z*HO4^rs#kT^*UXGVB#-+9^52TbddQvog~3MTd%{auh(Iw>vhUhyONIAD*kF%WNgRv zI%TR(vZnJF@6E~Q0puw*BonDMd7WZFC02ETZ#xC%^M55)xq}|z2?Q?oc^>AS^D^UX YW01V?Q_1!No=&(qR3VY*TALRB1v20>%K!iX literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/test_text.py b/lib/matplotlib/tests/test_text.py index 72fec721a43a..435da825a2cd 100644 --- a/lib/matplotlib/tests/test_text.py +++ b/lib/matplotlib/tests/test_text.py @@ -714,3 +714,9 @@ def test_update_mutate_input(): def test_invalid_color(): with pytest.raises(ValueError): plt.figtext(.5, .5, "foo", c="foobar") + + +@image_comparison(['text_pdf_kerning.pdf'], style='mpl20') +def test_pdf_kerning(): + plt.figure() + plt.figtext(0.1, 0.5, "ATATATATATATATATATA", size=30) From 12515636733e8214c4e4941675a3f5f06606c42a Mon Sep 17 00:00:00 2001 From: Frank Sauerburger Date: Thu, 25 Feb 2021 15:42:12 +0100 Subject: [PATCH 2/2] Add kerning to Type 3 font, ASCII strings in PDFs --- lib/matplotlib/backends/backend_pdf.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py index 42fa04b2fd47..26a12764da38 100644 --- a/lib/matplotlib/backends/backend_pdf.py +++ b/lib/matplotlib/backends/backend_pdf.py @@ -2287,24 +2287,26 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): } self.file._annotations[-1][1].append(link_annotation) - # If fonttype != 3 or there are no multibyte characters, emit the whole - # string at once. - if fonttype != 3 or all(ord(char) <= 255 for char in s): + # If fonttype != 3 emit the whole string at once without manual + # kerning. + if fonttype != 3: self.file.output(Op.begin_text, self.file.fontName(prop), fontsize, Op.selectfont) self._setup_textpos(x, y, angle) - self.file.output(self.encode_string(s, fonttype), Op.show, - Op.end_text) + self.file.output(self.encode_string(s, fonttype), + Op.show, Op.end_text) # There is no way to access multibyte characters of Type 3 fonts, as # they cannot have a CIDMap. Therefore, in this case we break the # string into chunks, where each chunk contains either a string of - # consecutive 1-byte characters or a single multibyte character. Each - # chunk is emitted with a separate command: 1-byte characters use the - # regular text show command (Tj), whereas multibyte characters use - # the XObject command (Do). (If using Type 42 fonts, all of this - # complication is avoided, but of course, those fonts can not be - # subsetted.) + # consecutive 1-byte characters or a single multibyte character. + # A sequence of 1-byte characters is broken into multiple chunks to + # adjust the kerning between adjacent chunks. Each chunk is emitted + # with a separate command: 1-byte characters use the regular text show + # command (TJ) with appropriate kerning between chunks, whereas + # multibyte characters use the XObject command (Do). (If using Type + # 42 fonts, all of this complication is avoided, but of course, + # subsetting those fonts is complex/hard to implement.) else: # List of (start_x, [prev_kern, char, char, ...]), w/o zero kerns. singlebyte_chunks = []