TTF font subsetting for PS backend

An initial revision of TTF font subsetting has been committed to SVN. It seems to work for all tests run by backend_driver.py (with the exception quiver_demo, which didn't seem to work without my changes either).

Some key results:

fonts_demo_kq_ps.py: 633518 -> 45232
mathtext_demo.py: 366268 -> 34932
unicode_demo.py: 92713 -> 27281

Over all the backend_driver demos, the size goes from 44,428,655 to 35,925,889.

The original ttconv code has been modified to be exception safe, since its error handling as a commandline app was to just quit the process. The easiest way to do this was to use C++ exceptions and add some destructors to various objects. It makes for a strange mix of C and C++, which hopefully isn't too offensive. I was more concerned with making the minimum number of changes to make it work in the new environment, rather than making stylistic ones for the sake of cleanliness etc.

ttconv supports outputting a Type 42 font (without subsetting), so matplotlib's old Type 42 output has been replaced with ttconv's. An rc value (ps.fonttype) can be used to select Type 3 or Type 42 output. This will probably go away (with Type 3 as the only option) in the future, but I thought I'd leave it in for testing purposes for now.

(I have been unable to test tex_unicode_demo.py, as my TeX installation doesn't seem to have all the necessary stuff (ucs.py) and installing that without root access is proving to be difficult... I suspect my changes will not affect this demo anyway, since use_tex uses a different method to embed the glyph outlines in the file.)

Please kick the tires and let me know how it goes,
Mike

An initial revision of TTF font subsetting has been committed to SVN.

Thank you for doing this.

[...]

ttconv supports outputting a Type 42 font (without subsetting), so
matplotlib's old Type 42 output has been replaced with ttconv's. An rc
value (ps.fonttype) can be used to select Type 3 or Type 42 output.

[...]

Please kick the tires and let me know how it goes,

Could you be more specific about how to test your changes? I dont see anything
in matplotlibrc.template, or in rcsetup.py, concerning the valid settings of
ps.fonttype. (rc settings should be validated, have a default value, and have
a commented listing in matplotlibrc.template.)

Thanks,
Darren

···

On Monday 09 July 2007 11:25:57 am Michael Droettboom wrote:

Also, when I run an older mpl or svn mpl, using simple_demo.py, I get
a font header that looks like the one below. It looks like I am not
getting the new stuff either...

%%BeginFont: BitstreamVeraSerif-Roman
%!PS-TrueType-1.0-2.0
8 dict begin
/FontName /BitstreamVeraSerif-Roman def
/FontMatrix [1 0 0 1 0 0] def
/FontType 42 def
/Encoding StandardEncoding def
/FontBBox [-375 -483 2636 1901] def
/PaintType 0 def
/FontInfo 7 dict dup begin
/Notice (Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.) def
/FamilyName (Bitstream Vera Serif) def
/FullName (Bitstream Vera Serif) def
/version (Release 1.10) def
/isFixedPitch false def
/UnderlinePosition -213 def
/UnderlineThickness 133 def
end readonly def
/sfnts [
<0001000000110100000400104F532F32B658F2650000D55C0000005650434C54798E6268
0000D5B400000036636D6170A4C3E8A00000B58800000358637674208F33ABF400001F04
000001946670676DE780F1C4000025F80000008B67617370000700070000EB340000000C
676C796627203BE80000268400008F0268646D78BBC32F430000D5EC0000154868656164
B5279A060000EB4000000036686865611045086F0000D53800000024686D747831C577F3
0000B8E0000004306B65726ECF55CE200000C1BC0000135C6C6F6361E324C0E00000BFA0
0000021A6D617870053D063B0000D518000000206E616D65D4B5E8800000011C00001DE5
706F7374B45A2FB10000BD100000028E70726570757906F6000020980000055E00000016
010E0001000000000000003A000000010000000000010014003A00010000000000020005
006100010000000000030014003A00010000000000040014003A0001000000000005000C
006600010000000000060018004E0001000000000007003000AF0001000000000008000E
086E000100000000000B00180985000100000000000D0913007200030001040900000074

···

On 7/9/07, Darren Dale <dd55@...143...> wrote:

Could you be more specific about how to test your changes? I dont see anything
in matplotlibrc.template, or in rcsetup.py, concerning the valid settings of
ps.fonttype. (rc settings should be validated, have a default value, and have
a commented listing in matplotlibrc.template.)

Sorry about that. I didn't notice the SVN login error the first time. It should be in SVN now.

The default is to output Type 3 fonts (i.e. the new way).

Darren: you mean rcdefaults.py, not rcsetup.py, right? I can't find an rcsetup.py.

Cheers,
Mike

John Hunter wrote:

···

On 7/9/07, Darren Dale <dd55@...143...> wrote:

Could you be more specific about how to test your changes? I dont see anything
in matplotlibrc.template, or in rcsetup.py, concerning the valid settings of
ps.fonttype. (rc settings should be validated, have a default value, and have
a commented listing in matplotlibrc.template.)
    
Also, when I run an older mpl or svn mpl, using simple_demo.py, I get
a font header that looks like the one below. It looks like I am not
getting the new stuff either...

%%BeginFont: BitstreamVeraSerif-Roman
%!PS-TrueType-1.0-2.0
8 dict begin
/FontName /BitstreamVeraSerif-Roman def
/FontMatrix [1 0 0 1 0 0] def
/FontType 42 def
/Encoding StandardEncoding def
/FontBBox [-375 -483 2636 1901] def
/PaintType 0 def
/FontInfo 7 dict dup begin
/Notice (Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.) def
/FamilyName (Bitstream Vera Serif) def
/FullName (Bitstream Vera Serif) def
/version (Release 1.10) def
/isFixedPitch false def
/UnderlinePosition -213 def
/UnderlineThickness 133 def
end readonly def
/sfnts [
<0001000000110100000400104F532F32B658F2650000D55C0000005650434C54798E6268
0000D5B400000036636D6170A4C3E8A00000B58800000358637674208F33ABF400001F04
000001946670676DE780F1C4000025F80000008B67617370000700070000EB340000000C
676C796627203BE80000268400008F0268646D78BBC32F430000D5EC0000154868656164
B5279A060000EB4000000036686865611045086F0000D53800000024686D747831C577F3
0000B8E0000004306B65726ECF55CE200000C1BC0000135C6C6F6361E324C0E00000BFA0
0000021A6D617870053D063B0000D518000000206E616D65D4B5E8800000011C00001DE5
706F7374B45A2FB10000BD100000028E70726570757906F6000020980000055E00000016
010E0001000000000000003A000000010000000000010014003A00010000000000020005
006100010000000000030014003A00010000000000040014003A0001000000000005000C
006600010000000000060018004E0001000000000007003000AF0001000000000008000E
086E000100000000000B00180985000100000000000D0913007200030001040900000074

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Something seems to be missing in the rcsetup

johnh@...539...:examples> rm -rf ~/.matplotlib/ttffont.cache
johnh@...539...:examples> PYTHONPATH=~/dev/lib/python2.4/site-packages/
python simple_plot.py -dPS
Traceback (most recent call last):
  File "simple_plot.py", line 18, in ?
    savefig('simple_plot')
  File "/home/titan/johnh/dev/lib/python2.4/site-packages/matplotlib/pylab.py",
line 802, in savefig
    return fig.savefig(*args, **kwargs)
  File "/home/titan/johnh/dev/lib/python2.4/site-packages/matplotlib/figure.py",
line 769, in savefig
    self.canvas.print_figure(*args, **kwargs)
  File "/home/titan/johnh/dev/lib/python2.4/site-packages/matplotlib/backends/backend_ps.py",
line 1039, in print_figure
    convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
KeyError: 'ps.fonttype'
johnh@...539...:examples>

···

On 7/9/07, Michael Droettboom <mdroe@...31...> wrote:

Sorry about that. I didn't notice the SVN login error the first time.
It should be in SVN now.

The default is to output Type 3 fonts (i.e. the new way).

Darren: you mean rcdefaults.py, not rcsetup.py, right? I can't find an
rcsetup.py.

Michael Droettboom wrote:

Sorry about that. I didn't notice the SVN login error the first time. It should be in SVN now.

The default is to output Type 3 fonts (i.e. the new way).

Darren: you mean rcdefaults.py, not rcsetup.py, right? I can't find an rcsetup.py.

Mike,

I renamed rcdefaults.py to rcsetup.py a few days ago. Try "svn update". Maybe that will solve your quiver_demo.py problem also; it has been working fine for me.

In general, I find that while working on mpl it is helpful to run svn update frequently, and always right before committing, so as to avoid conflicts and be sure that changes I make work with the latest changes others have made.

After svn update right now (to 3490), I am getting a compilation failure with the following error:

building 'matplotlib.ttf2ps' extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include -I/usr/include -I. -I/usr/include/python2.5 -c ttconv/pprdrv_tt.cpp -o build/temp.linux-i686-2.5/ttconv/pprdrv_tt.o
cc1plus: warning: command line option "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++
ttconv/pprdrv_tt.cpp: In function �void sfnts_glyf_table(TTStreamWriter&, TTFONT*, unsigned int, unsigned int)�:
ttconv/pprdrv_tt.cpp:579: error: �assert� was not declared in this scope
ttconv/pprdrv_tt.cpp: In function �void insert_ttfont(const char*, TTStreamWriter&, int, std::vector<int, std::allocator<int> >&)�:
ttconv/pprdrv_tt.cpp:1104: error: �assert� was not declared in this scope
error: command 'gcc' failed with exit status 1

Eric

Eric Firing wrote:

Michael Droettboom wrote:

Sorry about that. I didn't notice the SVN login error the first time. It should be in SVN now.
The default is to output Type 3 fonts (i.e. the new way).

Darren: you mean rcdefaults.py, not rcsetup.py, right? I can't find an rcsetup.py.

Mike,

I renamed rcdefaults.py to rcsetup.py a few days ago.

I have moved my new rcdefaults.py stuff into rcsetup.py.

After svn update right now (to 3490), I am getting a compilation failure with the following error:

Ah. Forgot to explicitly include <assert.h> (which older gcc's don't complain about).

All should be in SVN.

Cheers,
Mike

Michael Droettboom wrote:
[...]

All should be in SVN.

Mike,

Now it compiles and runs all the demos, and displays OK at normal resolution; but when I try to show it with gv or evince at 400%, gs crashes:
efiring@...340...:~/programs/py/mpl/matplotlib_units/examples$ evince simple_plot_ps.ps
ERROR: /unknownerror in --%op_show_continue--
Operand stack:

Execution stack:
    %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval--
Dictionary stack:
    --dict:1126/1686(ro)(G)-- --dict:0/20(G)-- --dict:103/200(L)-- --dict:6/7(L)--
Current allocation mode is local
Current file position is 16588
ESP Ghostscript 815.04: Unrecoverable error, exit code 1

** (evince:5270): WARNING **: Interpreter failed.

Eric

···

Cheers,
Mike

Oh dear. It works for me with my fairly old version of GNU ghostscript (7.07) and a couple different Postscript HP laser printers I tried. The file position where the error occurs at least seems plausible -- it's where the first text is shown.

I'll have to look into this further. More data points are welcome.

Cheers,
Mike

Eric Firing wrote:

···

Michael Droettboom wrote:
[...]

All should be in SVN.

Mike,

Now it compiles and runs all the demos, and displays OK at normal resolution; but when I try to show it with gv or evince at 400%, gs crashes:
efiring@...340...:~/programs/py/mpl/matplotlib_units/examples$ evince simple_plot_ps.ps
ERROR: /unknownerror in --%op_show_continue--
Operand stack:

Execution stack:
   %interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop 1 3 %oparray_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval--
Dictionary stack:
   --dict:1126/1686(ro)(G)-- --dict:0/20(G)-- --dict:103/200(L)-- --dict:6/7(L)--
Current allocation mode is local
Current file position is 16588
ESP Ghostscript 815.04: Unrecoverable error, exit code 1

** (evince:5270): WARNING **: Interpreter failed.

Eric

Cheers,
Mike