From: <edi...@gm...> - 2006-06-25 10:30:17
Attachments:
svn.patch
|
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 |
From: <edi...@gm...> - 2006-06-26 00:24:35
Attachments:
mathtext_demo.png
mathtext_demo.svg
|
QXQgbGFzdCwgc29tZSByZWFsIHByb2dyZXNzIQoKSSBkb24ndCBoYXZlIGEgZnJlc2ggU1ZOIGNv IGF0IGhvbWUgKGFuZCBJIGhhdmUgYSBkaWFsIHVwKSwgYnV0CnRvbW9ycm93IG1vcm5pbmcgSSds bCBzZW5kIGEgcGF0Y2ggYWdhaW5zdCB0aGUgU1ZOLgoKSSBmaXhlZCBhIGJpdCB0aGUgVW5pY29k ZUZvbnRzIGNsYXNzIHNvIG5vdyB0aGUgcmFzdGVyIChBZ2cpIGFuZCBTVkcKb3V0cHV0cyB3b3Jr LiBTVkcgbmVlZHMgYSBsaXR0bGUgbW9yZSBmaXhpbmcuCgpJIGJhc2ljYWx5IGRlZmluZWQgYSBu ZXcgY2xhc3MsIGJhc2VkIG9uIHRoZSBBcmlhbCBVbmljb2RlIE1TIGZvbnQuCmNsYXNzIEFyaWFs VW5pY29kZUZvbnRzKFVuaWNvZGVGb250cyk6CiAgICBiYXNlcGF0aCA9IHInQzpcV0lORE9XU1xG b250cycKICAgIGZhY2VmaWxlZGljdCA9IHsgJ2NhbCcgOiAnS1VOU1RMRVIuVFRGJywKICAgICAg ICAgICAgICAgICdybScgIDogJ3RpbWVzLnR0ZicsCiAgICAgICAgICAgICAgICAndHQnICA6ICdj b3VyLnR0ZicsCiAgICAgICAgICAgICAgICAnaXQnICA6ICdBUklBTFVOSS5UVEYnLAogICAgICAg ICAgICAgICAgTm9uZSAgOiAnQVJJQUxVTkkuVFRGJywKICAgICAgICAgICAgICAgIH0KCi4uLmFu ZCBqdXN0IHRoYXQhIEV2ZXJ5dGhpbmcgZWxzZSBpcyBpbmhlcml0ZWQgZnJvbSB0aGUgVW5pY29k ZUZvbnRzIGNsYXNzLgoKVGhlbiBJIHJhbiB0aGUgbWF0aHRleHRfZGVtby5weS4gVGhlIHJlc3Vs dHMgYXJlIGF0dGFjaGVkLgoKT24gNi8yNS8wNiwgRWRpbiBTYWxrb3ZpxIcgPGVkaW4uc2Fsa292 aWNAZ21haWwuY29tPiB3cm90ZToKPiBUaGlzIGlzIGEgbG9uZyBvbmUuCg== |
From: <edi...@gm...> - 2006-06-26 13:57:20
Attachments:
mathtext.patch
|
SSBnb3QgdGhlIFNWRyBiYWNrZW5kIHRvIHdvcmsgcHJvcGVybHkuIFRoZSBQUyBiYWNrZW5kIHNl ZW1zIHRvIGJlCnZlcnkgdGlnaHRseSBpbnRlZ3JhdGVkIHdpdGggdGhlIGN1cnJlbnQgaW1wbGVt ZW50YXRpb24gb2YgdGhlIEZvbnRzCmNsYXNzZXMgc28gSSBoYXZlbid0IHJlYWx5IGRpZ2dlZCBp bnRvIGl0IHlldC4KClRoaXMgcGF0Y2ggb25seSBhZGRzIGZvdXIgbmV3IGZpbGVzIGZvciBjb252 ZXJ0aW5nIFRlWC9UeXBlMSA8LT4KVW5pY29kZSwgYW5kIHRoZSBtb2RpZmllZCBtYXRodGV4dC5w eSBmaWxlLgoKRmVlbCBmcmVlIHRvIHNldHVwIHRoZSBjbGFzcyBNeVVuaWNvZGVGb250cyB3aXRo IHlvdXIgVW5pY29kZSBtYXRoCmZvbnQocyksIGFuZCB0aGVuIHVuY29tbWVudCB0aGUgY29yZXNw b25kaW5nIGxpbmVzIGluIHRoZQptYXRoX3BhcnNlX3NfZnQyZm9udF9jb21tb24gY2xhc3MgdG8g YWN0dWFsbHkgZW5hYmxlIHRoZQpNeVVuaWNvZGVGb250cyBjbGFzcyB0byBkbyBzb21ldGhpbmcg dXNlZnVsLgoKQ2hlZXJzCkVkaW4KCk9uIDYvMjYvMDYsIEVkaW4gU2Fsa292acSHIDxlZGluLnNh bGtvdmljQGdtYWlsLmNvbT4gd3JvdGU6Cj4gQXQgbGFzdCwgc29tZSByZWFsIHByb2dyZXNzIQo+ Cj4gSSBkb24ndCBoYXZlIGEgZnJlc2ggU1ZOIGNvIGF0IGhvbWUgKGFuZCBJIGhhdmUgYSBkaWFs IHVwKSwgYnV0Cj4gdG9tb3Jyb3cgbW9ybmluZyBJJ2xsIHNlbmQgYSBwYXRjaCBhZ2FpbnN0IHRo ZSBTVk4uCj4KPiBJIGZpeGVkIGEgYml0IHRoZSBVbmljb2RlRm9udHMgY2xhc3Mgc28gbm93IHRo ZSByYXN0ZXIgKEFnZykgYW5kIFNWRwo+IG91dHB1dHMgd29yay4gU1ZHIG5lZWRzIGEgbGl0dGxl IG1vcmUgZml4aW5nLgo+Cj4gSSBiYXNpY2FseSBkZWZpbmVkIGEgbmV3IGNsYXNzLCBiYXNlZCBv biB0aGUgQXJpYWwgVW5pY29kZSBNUyBmb250Lgo+IGNsYXNzIEFyaWFsVW5pY29kZUZvbnRzKFVu aWNvZGVGb250cyk6Cj4gICAgIGJhc2VwYXRoID0gcidDOlxXSU5ET1dTXEZvbnRzJwo+ICAgICBm YWNlZmlsZWRpY3QgPSB7ICdjYWwnIDogJ0tVTlNUTEVSLlRURicsCj4gICAgICAgICAgICAgICAg ICdybScgIDogJ3RpbWVzLnR0ZicsCj4gICAgICAgICAgICAgICAgICd0dCcgIDogJ2NvdXIudHRm JywKPiAgICAgICAgICAgICAgICAgJ2l0JyAgOiAnQVJJQUxVTkkuVFRGJywKPiAgICAgICAgICAg ICAgICAgTm9uZSAgOiAnQVJJQUxVTkkuVFRGJywKPiAgICAgICAgICAgICAgICAgfQo+Cj4gLi4u YW5kIGp1c3QgdGhhdCEgRXZlcnl0aGluZyBlbHNlIGlzIGluaGVyaXRlZCBmcm9tIHRoZSBVbmlj b2RlRm9udHMgY2xhc3MuCj4KPiBUaGVuIEkgcmFuIHRoZSBtYXRodGV4dF9kZW1vLnB5LiBUaGUg cmVzdWx0cyBhcmUgYXR0YWNoZWQuCj4KPiBPbiA2LzI1LzA2LCBFZGluIFNhbGtvdmnEhyA8ZWRp bi5zYWxrb3ZpY0BnbWFpbC5jb20+IHdyb3RlOgo+ID4gVGhpcyBpcyBhIGxvbmcgb25lLgo+Cj4K |
From: John H. <jdh...@ac...> - 2006-06-26 14:32:08
|
>>>>> "Edin" =3D=3D Edin Salkovi=A7 <edi...@gm...> writes: Edin> I got the SVG backend to work properly. The PS backend seems Edin> to be very tightly integrated with the current Edin> implementation of the Fonts classes so I haven't realy Edin> digged into it yet. Edin> This patch only adds four new files for converting TeX/Type1 Edin> <-> Unicode, and the modified mathtext.py file. A couple of comments * can we put all the dictionaries and data into a single file (_mathtext_data). I would rather not have a proliferation of support modules for mathtext * do we really need dictionaries for tex2uni and uni2tex. Would it not be better to define tex2uni and then do uni2tex =3D dict([(v,k) for k,v in tex2uni.items()]) JDH |