You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(33) |
Dec
(20) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(7) |
Feb
(44) |
Mar
(51) |
Apr
(43) |
May
(43) |
Jun
(36) |
Jul
(61) |
Aug
(44) |
Sep
(25) |
Oct
(82) |
Nov
(97) |
Dec
(47) |
2005 |
Jan
(77) |
Feb
(143) |
Mar
(42) |
Apr
(31) |
May
(93) |
Jun
(93) |
Jul
(35) |
Aug
(78) |
Sep
(56) |
Oct
(44) |
Nov
(72) |
Dec
(75) |
2006 |
Jan
(116) |
Feb
(99) |
Mar
(181) |
Apr
(171) |
May
(112) |
Jun
(86) |
Jul
(91) |
Aug
(111) |
Sep
(77) |
Oct
(72) |
Nov
(57) |
Dec
(51) |
2007 |
Jan
(64) |
Feb
(116) |
Mar
(70) |
Apr
(74) |
May
(53) |
Jun
(40) |
Jul
(519) |
Aug
(151) |
Sep
(132) |
Oct
(74) |
Nov
(282) |
Dec
(190) |
2008 |
Jan
(141) |
Feb
(67) |
Mar
(69) |
Apr
(96) |
May
(227) |
Jun
(404) |
Jul
(399) |
Aug
(96) |
Sep
(120) |
Oct
(205) |
Nov
(126) |
Dec
(261) |
2009 |
Jan
(136) |
Feb
(136) |
Mar
(119) |
Apr
(124) |
May
(155) |
Jun
(98) |
Jul
(136) |
Aug
(292) |
Sep
(174) |
Oct
(126) |
Nov
(126) |
Dec
(79) |
2010 |
Jan
(109) |
Feb
(83) |
Mar
(139) |
Apr
(91) |
May
(79) |
Jun
(164) |
Jul
(184) |
Aug
(146) |
Sep
(163) |
Oct
(128) |
Nov
(70) |
Dec
(73) |
2011 |
Jan
(235) |
Feb
(165) |
Mar
(147) |
Apr
(86) |
May
(74) |
Jun
(118) |
Jul
(65) |
Aug
(75) |
Sep
(162) |
Oct
(94) |
Nov
(48) |
Dec
(44) |
2012 |
Jan
(49) |
Feb
(40) |
Mar
(88) |
Apr
(35) |
May
(52) |
Jun
(69) |
Jul
(90) |
Aug
(123) |
Sep
(112) |
Oct
(120) |
Nov
(105) |
Dec
(116) |
2013 |
Jan
(76) |
Feb
(26) |
Mar
(78) |
Apr
(43) |
May
(61) |
Jun
(53) |
Jul
(147) |
Aug
(85) |
Sep
(83) |
Oct
(122) |
Nov
(18) |
Dec
(27) |
2014 |
Jan
(58) |
Feb
(25) |
Mar
(49) |
Apr
(17) |
May
(29) |
Jun
(39) |
Jul
(53) |
Aug
(52) |
Sep
(35) |
Oct
(47) |
Nov
(110) |
Dec
(27) |
2015 |
Jan
(50) |
Feb
(93) |
Mar
(96) |
Apr
(30) |
May
(55) |
Jun
(83) |
Jul
(44) |
Aug
(8) |
Sep
(5) |
Oct
|
Nov
(1) |
Dec
(1) |
2016 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(3) |
Sep
(1) |
Oct
(3) |
Nov
|
Dec
|
2017 |
Jan
|
Feb
(5) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
|
Sep
(7) |
Oct
|
Nov
|
Dec
|
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
1
|
2
(1) |
3
(4) |
4
|
5
|
6
(15) |
7
(2) |
8
(1) |
9
(3) |
10
|
11
|
12
(8) |
13
(6) |
14
(4) |
15
(6) |
16
(1) |
17
|
18
(1) |
19
(4) |
20
|
21
|
22
(7) |
23
(12) |
24
(2) |
25
(1) |
26
(3) |
27
|
28
(2) |
29
(1) |
30
(2) |
|
This is a long one. The problem with the last patch I submitted was a no brainer. Instead of: math_parse_s_ft2font_ps = math_parse_s_ft2font_common('PS') should have been: math_parse_s_ps = math_parse_s_ft2font_common('PS') I am now in the process of creating a UnicodeFonts class, and a derived BakomaUnicodeFonts, which is a hack to add "unicode support" to the Bakoma fonts. Is BakomaUnicodeFonts worth of implementing? I must say that I had a lot of problems in reading/understanding the code of the current Fonts classes, especially regarding the ambiguous usage of the word "font". I also tried to make a common parent class in order to abstract the common properties of the BakomaTrueTypeFonts and BakomaPSFonts classes (something along the way of what I did with the math_parse_s_ft2font_common class), but I hit the wall - there was a lot of black magic under the hood, IMHO. So I decided to make naming changes in the new Unicode aware classes, and that's the purpose of writing this email before I got the new classes to work. So please John, do comment on this, because I don't know whether I'm breaking something, and whether the names are chosen appropriately. The changes I made, make no effect on the current code - that is, everything still works. I'm sending you a patch against the SVN tree. I also added the automatically genarated tex2uni etc. files, and they are now incorporated in the patch. What should we do with the script that generates those file. Should I try to integrate it into the setup/build process? These are the new imports: from matplotlib.tex2uni import tex2uni from matplotlib.type12uni import type12uni These are the new top-level functions I defined in mathtext: def font_open(filename): ext = filename.rsplit('.',1)[1] if ext == 'afm': return AFM(filename) else: return FT2Font(filename) def get_unicode_index(symbol): """get_unicode_index(symbol) -> integer Return the integer index from the Unicode table of an Unicode symbol """ try:# This will succeed if symbol is a single unicode char return ord(symbol) except TypeError: pass try:# Is symbol a TeX symbol (i.e. \alpha) return tex2uni[symbol] except KeyError: pass try:# Is symbol a Type1 name (i.e. degree)? If not raise error return type12uni[symbol] except KeyError: message = """'%(symbol)s' is not a valid Unicode character or TeX/Type1 symbol"""%locals() raise ValueError, message And finally, these are the new classes: ==== class UnicodeFonts(Fonts): """An abstract base class for handling Unicode fonts. Specific terminology: * fontface: an FT2Font object, corresponding to a facename * facename: a string that defines the (type)face's name - 'rm', 'it' etc. * filename: a string that is used for generating a fontface object * symbol*: a single Unicode character or a TeX command, or to be precise, a TeX symbol command like \alpha (but not \frac) or even a Type1/PS name * filenamesdict: a dict that maps the face's name to the filename: filenamesdict = { 'cal' : 'fontnamecal.ext', 'rm' : 'fontnamerm.ext', 'tt' : 'fontnamett.ext', 'it' : 'fontnameit.ext', None : 'fontnamesmth.ext'} filenamesdict should be declared as a class atribute * glyphdict: a dict used for caching of glyph specific data * fontsdict: a dict of facename -> fontface pairs * charmaps: a dict of facename -> charmap pairs * glyphmaps: a dict of facename -> glyphmap pairs. A glyphmap is an inverted charmap * output: a string in ['BMP','SVG','PS'], coresponding to the backends * index: Fontfile specific index of a glyph/char. Taken from a charmap. """ # The path to the dir with the fontfiles basepath = get_data_path() def __init__(self, output='BMP'): if output: self.output = output # dict self.glyphdict[key] = facename, metrics, glyph, offset self.glyphdict = {} self.fontsdict = dict( [ (facename, font_open(os.path.join(self.basepath, filenamesdict[facename]))) for facename in self.facenames]) # a dict of glyphindex -> charcode pairs self.charmaps = dict( [ (facename, self.fontsdict[facename].get_charmap())\ for facename in self.facenames]) # a dict of charcode -> glyphindex pairs self.glyphmaps = {} for facename in self.facenames: charmap = self.charmaps[facename] self.glyphmaps[facename] = dict([(charcode, glyphind) for glyphind, charcode in charmap.items()]) for fontface in self.fontsdict.values(): fontface.clear() if self.output == 'SVG': # a list of "glyphs" we need to render this thing in SVG self.svg_glyphs=[] def set_canvas_size(self, w, h, pswriter=None): 'Dimension the drawing canvas; may be a noop' # self.width = int(w) # self.height = int(h) # I don't know why this was different than the PS version self.width = w self.height = h if pswriter: self.pswriter = pswriter else: for fontface in self.fontsdict.values(): fontface.set_bitmap_size(int(w), int(h)) def render(self, ox, oy, facename, symbol, fontsize, dpi): filename = self.filenamesdict[facename] metrics, glyph, offset = self._get_info(facename, symbol, fontsize, dpi) index = self._get_unicode_index(symbol) if self.output == 'SVG': oy += offset - 512/2048.*10. self.svg_glyphs.append((filename, fontsize, index, ox, oy, metrics)) elif self.output == 'PS': # This should be changed to check for math mode or smth. #if filename == 'cmex10.ttf': # oy += offset - 512/2048.*10. psfontname = self.fontsdict[facename].postscript_name ps = """/%(psfontname)s findfont %(fontsize)s scalefont setfont %(ox)f %(oy)f moveto /%(glyphname)s glyphshow """ % locals() self.pswriter.write(ps) else: # BMP fontface = self.fontsdict[facename] fontface.draw_glyph_to_bitmap( int(ox), int(self.height - oy - metrics.ymax), glyph) def get_metrics(self, facename, symbol, fontsize, dpi): metrics, glyph, offset = \ self._get_info(facename, symbol, fontsize, dpi) return metrics def _get_unicode_index(self, symbol): return get_unicode_index(symbol) # Methods that must be overridden def _get_info(self, facename, symbol, fontsize, dpi): raise NotImplementedError('Derived must override') class BakomaUnicodeFonts(UnicodeFonts): """A class that simulates Unicode support in the BaKoMa fonts""" filenamesdict = { 'cal' : 'cmsy10.ttf', 'rm' : 'cmr10.ttf', 'tt' : 'cmtt10.ttf', 'it' : 'cmmi10.ttf', } def _get_info(self, facename, symbol, fontsize, dpi): 'load the facename, metrics and glyph' #print hex(index), symbol, filename, facename key = facename, symbol, fontsize, dpi tup = self.glyphdict.get(key) if tup is not None: return tup filename = self.fontmap[facename] # This is black magic to me (Edin) if self.output == 'PS': if filename not in bakoma_fonts: bakoma_fonts.append(filename) fontface = self.fontsdict[facename] fontface.set_size(fontsize, dpi) head = fontface.get_sfnt_table('head') index = self._get_index(symbol) glyph = fontface.load_char(index) xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox] # This is black magic to me (Edin) if filename == 'cmex10.ttf': if self.output == 'PS': offset = -(head['yMin']+512)/head['unitsPerEm']*10. else: offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0 else: offset = 0. metrics = Bunch( advance = glyph.linearHoriAdvance/65536.0, height = glyph.height/64.0, width = glyph.width/64.0, xmin = xmin, xmax = xmax, ymin = ymin+offset, ymax = ymax+offset, ) self.glyphdict[key] = metrics, glyph, offset return self.glyphdict[key] # We override the UnicodeFonts method def _get_unicode_index(self, symbol): pass ==== Cheers, Edin