Revision: 4126 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4126&view=rev Author: mdboom Date: 2007-11-06 10:32:30 -0800 (Tue, 06 Nov 2007)
Log Message: ----------- Prevent errors when using OpenType CFF fonts. This means turning off subsetting on backend_pdf, and raising an exception in backend_ps. Modified Paths: -------------- trunk/matplotlib/examples/mathtext_examples.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/lib/matplotlib/font_manager.py trunk/matplotlib/lib/matplotlib/mathtext.py Modified: trunk/matplotlib/examples/mathtext_examples.py =================================================================== --- trunk/matplotlib/examples/mathtext_examples.py 2007-11-06 18:23:13 UTC (rev 4125) +++ trunk/matplotlib/examples/mathtext_examples.py 2007-11-06 18:32:30 UTC (rev 4126) @@ -49,7 +49,7 @@ r'$\widehat{abc}\widetilde{def}$', r'$\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega$', r'$\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \lambda \mu \nu \xi \pi \kappa \rho \sigma \tau \upsilon \phi \chi \psi$', - ur'Generic symbol: $\u23ce \mathrm{\ue0f2}$' + ur'Generic symbol: $\u23ce \mathrm{\ue0f2 \U0001D538}$' ] from pylab import * Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-11-06 18:23:13 UTC (rev 4125) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-11-06 18:32:30 UTC (rev 4126) @@ -9,6 +9,7 @@ import re import sys import time +import warnings import zlib import numpy as npy @@ -25,7 +26,7 @@ FigureManagerBase, FigureCanvasBase from matplotlib.cbook import Bunch, enumerate, is_string_like, reverse_dict, get_realpath_and_stat from matplotlib.figure import Figure -from matplotlib.font_manager import findfont +from matplotlib.font_manager import findfont, is_opentype_cff_font from matplotlib.afm import AFM import matplotlib.type1font as type1font import matplotlib.dviread as dviread @@ -786,7 +787,8 @@ glyph = font.load_char(ccode, flags=LOAD_NO_HINTING) # Why divided by 3.0 ??? Wish I knew... MGD widths.append((ccode, cvt(glyph.horiAdvance) / 3.0)) - cid_to_gid_map[ccode] = unichr(gind) + if ccode < 65536: + cid_to_gid_map[ccode] = unichr(gind) max_ccode = max(ccode, max_ccode) widths.sort() cid_to_gid_map = cid_to_gid_map[:max_ccode + 1] @@ -876,6 +878,15 @@ 'StemV' : 0 # ??? } + # The font subsetting to a Type 3 font does not work for + # OpenType (.otf) that embed a Postscript CFF font, so avoid that -- + # save as a (non-subsetted) Type 42 font instead. + if is_opentype_cff_font(filename): + fonttype = 42 + warnings.warn(("'%s' can not be subsetted into a Type 3 font. " + + "The entire font will be embedded in the output.") % + os.path.basename(filename)) + if fonttype == 3: return embedTTFType3(font, characters, descriptor) elif fonttype == 42: @@ -1134,10 +1145,6 @@ self.truetype_font_cache = {} self.afm_font_cache = {} self.file.used_characters = self.used_characters = {} - if rcParams['pdf.fonttype'] == 3: - self.encode_string = self.encode_string_type3 - else: - self.encode_string = self.encode_string_type42 self.mathtext_parser = MathTextParser("Pdf") self.image_magnification = dpi/72.0 self.tex_font_map = None @@ -1344,7 +1351,7 @@ # When using Type 3 fonts, we can't use character codes higher # than 255, so we use the "Do" command to render those # instead. - fonttype = rcParams['pdf.fonttype'] + global_fonttype = rcParams['pdf.fonttype'] # Set up a global transformation matrix for the whole math expression a = angle / 180.0 * pi @@ -1357,6 +1364,11 @@ prev_font = None, None oldx, oldy = 0, 0 for ox, oy, fontname, fontsize, num, symbol_name in glyphs: + if is_opentype_cff_font(fontname): + fonttype = 42 + else: + fonttype = global_fonttype + if fonttype == 42 or num <= 255: self._setup_textpos(ox, oy, 0, oldx, oldy) oldx, oldy = ox, oy @@ -1364,14 +1376,19 @@ self.file.output(self.file.fontName(fontname), fontsize, Op.selectfont) prev_font = fontname, fontsize - self.file.output(self.encode_string(unichr(num)), Op.show) + self.file.output(self.encode_string(unichr(num), fonttype), Op.show) self.file.output(Op.end_text) # If using Type 3 fonts, render all of the two-byte characters # as XObjects using the 'Do' command. - if fonttype == 3: + if global_fonttype == 3: for ox, oy, fontname, fontsize, num, symbol_name in glyphs: - if num > 255: + if is_opentype_cff_font(fontname): + fonttype = 42 + else: + fonttype = global_fonttype + + if fonttype == 3 and num > 255: self.file.output(Op.gsave, 0.001 * fontsize, 0, 0, 0.001 * fontsize, @@ -1471,10 +1488,9 @@ self.draw_polygon(boxgc, gc._rgb, ((x1,y1), (x2,y2), (x3,y3), (x4,y4))) - def encode_string_type3(self, s): - return s.encode('cp1252', 'replace') - - def encode_string_type42(self, s): + def encode_string(self, s, fonttype): + if fonttype == 3: + return s.encode('cp1252', 'replace') return s.encode('utf-16be', 'replace') def draw_text(self, gc, x, y, s, prop, angle, ismath=False): @@ -1500,20 +1516,29 @@ font = self._get_font_afm(prop) l, b, w, h = font.get_str_bbox(s) y -= b * fontsize / 1000 + fonttype = 42 else: font = self._get_font_ttf(prop) self.track_characters(font, s) font.set_text(s, 0.0, flags=LOAD_NO_HINTING) y += font.get_descent() / 64.0 + fonttype = rcParams['pdf.fonttype'] + + # We can't subset all OpenType fonts, so switch to Type 42 + # in that case. + if is_opentype_cff_font(font.fname): + fonttype = 42 + def check_simple_method(s): """Determine if we should use the simple or woven method - to output this text, and chunks the string into 1-bit and - 2-bit sections if necessary.""" + to output this text, and chunks the string into 1-byte and + 2-byte sections if necessary.""" use_simple_method = True chunks = [] - if rcParams['pdf.fonttype'] == 3: - if not isinstance(s, str) and len(s) != 0: + + if not rcParams['pdf.use14corefonts']: + if fonttype == 3 and not isinstance(s, str) and len(s) != 0: # Break the string into chunks where each chunk is either # a string of chars <= 255, or a single character > 255. s = unicode(s) @@ -1537,7 +1562,7 @@ prop.get_size_in_points(), Op.selectfont) self._setup_textpos(x, y, angle) - self.file.output(self.encode_string(s), Op.show, Op.end_text) + self.file.output(self.encode_string(s, fonttype), Op.show, Op.end_text) def draw_text_woven(chunks): """Outputs text using the woven method, alternating @@ -1567,7 +1592,7 @@ for chunk_type, chunk in chunks: if mode == 1 and chunk_type == 1: self._setup_textpos(newx, 0, 0, oldx, 0, 0) - self.file.output(self.encode_string(chunk), Op.show) + self.file.output(self.encode_string(chunk, fonttype), Op.show) oldx = newx lastgind = None Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-11-06 18:23:13 UTC (rev 4125) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-11-06 18:32:30 UTC (rev 4126) @@ -18,7 +18,7 @@ from matplotlib.cbook import is_string_like, izip, get_realpath_and_stat from matplotlib.figure import Figure -from matplotlib.font_manager import findfont +from matplotlib.font_manager import findfont, is_opentype_cff_font from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING from matplotlib.ttconv import convert_ttf_to_ps from matplotlib.mathtext import MathTextParser @@ -1030,7 +1030,7 @@ else: self._print_figure(outfile, format, dpi, facecolor, edgecolor, orientation, isLandscape, papertype) - + def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', orientation='portrait', isLandscape=False, papertype=None): """ @@ -1134,7 +1134,15 @@ for c in chars: gind = cmap.get(ord(c)) or 0 glyph_ids.append(gind) - convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) + # The ttf to ps (subsetting) support doesn't work for + # OpenType fonts that are Postscript inside (like the + # STIX fonts). This will simply turn that off to avoid + # errors. + if is_opentype_cff_font(font_filename): + raise RuntimeError("OpenType CFF fonts can not be saved using the internal Postscript backend at this time.\nConsider using the Cairo backend.") + else: + fonttype = rcParams['ps.fonttype'] + convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) print >>fh, "end" print >>fh, "%%EndProlog" Modified: trunk/matplotlib/lib/matplotlib/font_manager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/font_manager.py 2007-11-06 18:23:13 UTC (rev 4125) +++ trunk/matplotlib/lib/matplotlib/font_manager.py 2007-11-06 18:32:30 UTC (rev 4126) @@ -1059,6 +1059,25 @@ return self.defaultFont return fname + +_is_opentype_cff_font_cache = {} +def is_opentype_cff_font(filename): + """ + Returns True if the given font is a Postscript Compact Font Format + Font embedded in an OpenType wrapper. + """ + if os.path.splitext(filename)[1].lower() == '.otf': + result = _is_opentype_cff_font_cache.get(filename) + if result is None: + fd = open(filename, 'rb') + tag = fd.read(4) + fd.close() + result = (tag == 'OTTO') + _is_opentype_cff_font_cache[filename] = result + return result + return False + + if USE_FONTCONFIG and sys.platform != 'win32': import re Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-11-06 18:23:13 UTC (rev 4125) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-11-06 18:32:30 UTC (rev 4126) @@ -1945,7 +1945,8 @@ ) | Error(r"Expected \hspace{n}")) ).setParseAction(self.customspace).setName('customspace') - symbol =(Regex(ur"([a-zA-Z0-9 +\-*/<>=:,.;!'@()\u0080-\uffff])|(\\[%${}\[\]])") + unicode_range = u"\U00000080-\U0001ffff" + symbol =(Regex(UR"([a-zA-Z0-9 +\-*/<>=:,.;!'@()%s])|(\\[%%${}\[\]])" % unicode_range) | Combine( bslash + oneOf(tex2uni.keys()) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Matplotlib-checkins mailing list Matplotlib-checkins@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins