def __init__(self, width, height, dpi): RendererBase.__init__(self) self.dpi = dpi self.width = width self.height = height self._renderer = _RendererAgg(int(width), int(height), dpi) self._filter_renderers = [] self._update_methods() self.mathtext_parser = MathTextParser('Agg') self.bbox = Bbox.from_bounds(0, 0, self.width, self.height)
def __init__(self, dpi, width, height): super(RendererGR, self).__init__() self.dpi = dpi if __version__[0] >= '2': self.nominal_fontsize = 0.001625 default_dpi = 100 else: self.nominal_fontsize = 0.0013 default_dpi = 80 self.width = float(width) * dpi / default_dpi self.height = float(height) * dpi / default_dpi self.mathtext_parser = MathTextParser('agg') self.texmanager = TexManager()
def updateShape(self): try: self.bitmapName = './tmp/tex_bmp_' + str(self.uid) + '.png' q = MathTextParser('Bitmap') q.to_png(self.bitmapName, self.parameter['LaTex'].value) self.png = QPixmap(self.bitmapName) except: print ('>>> ERROR ImageLaTex.updateShape') print (' Syntax Error - chyba pri update/parsovani LaTex retazca alebo renedrovani') print (' obrazku ' + self.bitmapName) self.png = QPixmap(self.path + '/img/error_tex_format.png')
def __init__(self): """ Initialization """ self.mathtext_parser = MathTextParser('path') self.tex_font_map = None from matplotlib.cbook import maxdict self._ps_fontd = maxdict(50) self._texmanager = None self._adobe_standard_encoding = None
def __init__(self, width, height, svgwriter, basename=None): self.width = width self.height = height self._svgwriter = svgwriter self._groupd = {} if not rcParams['svg.image_inline']: assert basename is not None self.basename = basename self._imaged = {} self._clipd = {} self._char_defs = {} self.mathtext_parser = MathTextParser('SVG') svgwriter.write(svgProlog % (width, height, width, height))
def __init__(self, dpi): self.dpi = dpi self.width = 640.0 * dpi / 80 self.height = 480.0 * dpi / 80 mwidth, mheight, width, height = gr.inqdspsize() if (width / (mwidth / 0.0256) < 200): mwidth *= self.width / width gr.setwsviewport(0, mwidth, 0, mwidth * 0.75) else: gr.setwsviewport(0, 0.192, 0, 0.144) gr.setwswindow(0, 1, 0, 0.75) gr.setviewport(0, 1, 0, 0.75) gr.setwindow(0, self.width, 0, self.height) self.mathtext_parser = MathTextParser('agg') self.texmanager = TexManager()
def render_latex_mpl(text, path, color=(0, 0, 0), dpi=600, output="png"): r""" Render a LaTeX-formula into an image with matplotlib. Parameters ---------- text : string String containing the latex-code. path : string Path to the file to be saved. color : tuple, optional color of the text given as rgb tuple. Default: ``(0, 0, 0)`` dpi : int, optional Used dpi. Default: 1200 output : string, optional Output format. Default: ``"png"`` Notes ----- If you get the following error: ``RuntimeError: libpng signaled error`` Try to set the dpi higher. (1200 recomended) If big symbols like ``\int`` or ``\sum`` don't show up properly, try setting a ``\displaystyle`` infront of them. """ from matplotlib.mathtext import MathTextParser from matplotlib.font_manager import FontProperties from matplotlib import figure, rc # backend_agg supports all of the core output formats from matplotlib.backends import backend_agg rc("text", usetex=False) prop = FontProperties() parser = MathTextParser("path") width, height, depth, _, _ = parser.parse(text, dpi=72, prop=prop) fig = figure.Figure(figsize=(width / 72.0, height / 72.0)) fig.text(0, depth / height, text, fontproperties=prop, color=color) backend_agg.FigureCanvasAgg(fig) fig.savefig(path, dpi=dpi, format=output, transparent=True)
def render(plotables, fmt='svg', **kwargs): """renders several Plot objects""" import matplotlib.pyplot as plt # extract optional arguments used for rasterization printargs, kwargs = itertools2.dictsplit( kwargs, ['dpi', 'transparent', 'facecolor', 'background', 'figsize']) ylim = kwargs.pop('ylim', None) xlim = kwargs.pop('xlim', None) title = kwargs.pop('title', None) fig, ax = plt.subplots() labels = kwargs.pop('labels', [None] * len(plotables)) # slightly shift the points to make superimposed curves more visible offset = kwargs.pop('offset', 0) for i, obj in enumerate(plotables): if labels[i] is None: labels[i] = str(obj) if not title: try: title = obj._repr_latex_() # check that title can be used in matplotlib from matplotlib.mathtext import MathTextParser parser = MathTextParser('path').parse(title) except Exception as e: title = labels[i] ax = obj._plot(ax, label=labels[i], offset=i * offset, **kwargs) if ylim: plt.ylim(ylim) if xlim: plt.xlim(xlim) ax.set_title(title) if len(labels) > 1: ax.legend() output = io.BytesIO() fig.savefig(output, format=fmt, **printargs) data = output.getvalue() plt.close(fig) return data
def math_to_image(s, filename_or_obj, prop=None, dpi=None, format=None): """ Given a math expression, renders it in a closely-clipped bounding box to an image file. *s* A math expression. The math portion should be enclosed in dollar signs. *filename_or_obj* A filepath or writable file-like object to write the image data to. *prop* If provided, a FontProperties() object describing the size and style of the text. *dpi* Override the output dpi, otherwise use the default associated with the output format. *format* The output format, eg. 'svg', 'pdf', 'ps' or 'png'. If not provided, will be deduced from the filename. """ from matplotlib import figure # backend_agg supports all of the core output formats from matplotlib.backends import backend_agg from matplotlib.font_manager import FontProperties from matplotlib.mathtext import MathTextParser if prop is None: prop = FontProperties() parser = MathTextParser('path') width, height, depth, _, _ = parser.parse(s, dpi=72, prop=prop) fig = figure.Figure(figsize=(width / 72.0, height / 72.0)) fig.text(0, depth / height, s, fontproperties=prop) backend_agg.FigureCanvasAgg(fig) fig.savefig(filename_or_obj, dpi=dpi, format=format) return depth
def __init__(self, width, height, dpi): if __debug__: verbose.report('RendererAgg.__init__', 'debug-annoying') RendererBase.__init__(self) self.dpi = dpi self.width = width self.height = height if __debug__: verbose.report('RendererAgg.__init__ width=%s, height=%s'%(width, height), 'debug-annoying') self._renderer = _RendererAgg(int(width), int(height), dpi, debug=False) self._filter_renderers = [] if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done', 'debug-annoying') self._update_methods() self.mathtext_parser = MathTextParser('Agg') self.bbox = Bbox.from_bounds(0, 0, self.width, self.height) if __debug__: verbose.report('RendererAgg.__init__ done', 'debug-annoying')
def __init__(self, width, height, svgwriter, basename=None): self.width = width self.height = height self._svgwriter = svgwriter if rcParams['path.simplify']: self.simplify = (width, height) else: self.simplify = None self._groupd = {} if not rcParams['svg.image_inline']: assert basename is not None self.basename = basename self._imaged = {} self._clipd = {} self._char_defs = {} self._markers = {} self._path_collection_id = 0 self._imaged = {} self.mathtext_parser = MathTextParser('SVG') svgwriter.write(svgProlog % (width, height, width, height))
def __init__(self, width, height, ctx, dpi=72): self.width = width self.height = height self.dpi = dpi self.ctx = ctx self._image_count = 0 # used to uniquely label each image created in this figure... # define the js context self.ctx.width = width self.ctx.height = height #self.ctx.textAlign = "center"; self.ctx.textBaseline = "alphabetic" self.flip = Affine2D().scale(1, -1).translate(0, height) self.mathtext_parser = MathTextParser('bitmap') self._path_time = 0 self._text_time = 0 self._marker_time = 0 self._sub_time = 0 self._last_clip = None self._last_clip_path = None self._clip_count = 0
def __init__(self, width, height, svgwriter, basename=None, image_dpi=72): self.width = width self.height = height self.writer = XMLWriter(svgwriter) self.image_dpi = image_dpi # the actual dpi we want to rasterize stuff with self._groupd = {} if not rcParams['svg.image_inline']: assert basename is not None self.basename = basename self._imaged = {} self._clipd = OrderedDict() self._char_defs = {} self._markers = {} self._path_collection_id = 0 self._imaged = {} self._hatchd = OrderedDict() self._has_gouraud = False self._n_gradients = 0 self._fonts = OrderedDict() self.mathtext_parser = MathTextParser('SVG') RendererBase.__init__(self) self._glyph_map = dict() str_height = short_float_fmt(height) str_width = short_float_fmt(width) svgwriter.write(svgProlog) # Changes starts here for Image Truncation # Changed from integer to float to accept decimals self._start_id = self.writer.start( 'svg', width='%dpt' % str_width, height='%dpt' % str_height, viewBox='0 0 %d %d' % (str_width, str_height), xmlns="http://www.w3.org/2000/svg", version="1.1", attrib={'xmlns:xlink': "http://www.w3.org/1999/xlink"}) self._write_default_style()
def __init__(self, width, height, dpi): if __debug__: verbose.report('RendererAgg.__init__', 'debug-annoying') RendererBase.__init__(self) self.dpi = dpi self.width = width self.height = height if __debug__: verbose.report('RendererAgg.__init__ width=%s, height=%s'%(width, height), 'debug-annoying') self._renderer = _RendererAgg(int(width), int(height), dpi, debug=False) if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done', 'debug-annoying') self.draw_path = self._renderer.draw_path self.draw_markers = self._renderer.draw_markers self.draw_path_collection = self._renderer.draw_path_collection self.draw_quad_mesh = self._renderer.draw_quad_mesh self.draw_image = self._renderer.draw_image self.copy_from_bbox = self._renderer.copy_from_bbox self.restore_region = self._renderer.restore_region self.tostring_rgba_minimized = self._renderer.tostring_rgba_minimized self.mathtext_parser = MathTextParser('Agg') self.bbox = Bbox.from_bounds(0, 0, self.width, self.height) if __debug__: verbose.report('RendererAgg.__init__ done', 'debug-annoying')
def __init__(self, width, height, svgwriter, basename=None): self.width = width self.height = height self._svgwriter = svgwriter self._groupd = {} if not rcParams['svg.image_inline']: assert basename is not None self.basename = basename self._imaged = {} self._clipd = {} self._char_defs = {} self._markers = {} self._path_collection_id = 0 self._imaged = {} self._hatchd = {} self._n_gradients = 0 self.mathtext_parser = MathTextParser('SVG') RendererBase.__init__(self) self._glyph_map = dict() svgwriter.write(svgProlog % (width, height, width, height))
def __init__(self, width, height, pswriter, dpi=72): RendererBase.__init__(self) self.width = width self.height = height self._pswriter = pswriter if rcParams['text.usetex']: self.textcnt = 0 self.psfrag = [] # current renderer state (None=uninitialised) self.color = None self.linewidth = None self.linejoin = None self.linecap = None self.linedash = None self.fontname = None self.fontsize = None self.hatch = None self.image_magnification = dpi / 72.0 self._clip_paths = {} self._path_collection_id = 0 self.used_characters = {} self.mathtext_parser = MathTextParser("PS")
def plot_attention(image, predicted_labels, rf_coords, alignment_history, time=0): """Plot the highest attention region for image at time t in the decoding""" fig, axes = plt.subplots(2, 1, figsize=(12, 6)) axes[0].set_title("Highest alignment score") axes[0].imshow(np.squeeze(image), cmap='gray') rf_coords_flat = np.reshape(rf_coords, (-1, 4)) idx = alignment_history.argmax(axis=1) i, score = idx[time], alignment_history[np.arange(len(alignment_history)), idx][time] bbox = rf_coords_flat[i] plot_bbox(axes[0], bbox, score) check_parser = MathTextParser('MacOSX') kwargs = { 'x': 0.0, 'y': 0.5, 'size': 30, 'verticalalignment': 'center', 'horizontalalignment': 'left' } axes[1].set_title("Prediction so far") predicted_formula = "$" + convert_to_formula( predicted_labels[0][:time]) + "$" try: check_parser.parse(predicted_formula) axes[1].text(s=predicted_formula, **kwargs) except ValueError: kwargs['size'] = 15 axes[1].text(s=predicted_formula[1:-1].replace(' ', ''), **kwargs)
class RendererCairo(RendererBase): mathtext_parser = _api.deprecated("3.4")( property(lambda self: MathTextParser('Cairo'))) def __init__(self, dpi): self.dpi = dpi self.gc = GraphicsContextCairo(renderer=self) self.text_ctx = cairo.Context( cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1)) super().__init__() def set_ctx_from_surface(self, surface): self.gc.ctx = cairo.Context(surface) # Although it may appear natural to automatically call # `self.set_width_height(surface.get_width(), surface.get_height())` # here (instead of having the caller do so separately), this would fail # for PDF/PS/SVG surfaces, which have no way to report their extents. def set_width_height(self, width, height): self.width = width self.height = height def _fill_and_stroke(self, ctx, fill_c, alpha, alpha_overrides): if fill_c is not None: ctx.save() if len(fill_c) == 3 or alpha_overrides: ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], alpha) else: ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], fill_c[3]) ctx.fill_preserve() ctx.restore() ctx.stroke() def draw_path(self, gc, path, transform, rgbFace=None): # docstring inherited ctx = gc.ctx # Clip the path to the actual rendering extents if it isn't filled. clip = (ctx.clip_extents() if rgbFace is None and gc.get_hatch() is None else None) transform = (transform + Affine2D().scale(1, -1).translate(0, self.height)) ctx.new_path() _append_path(ctx, path, transform, clip) self._fill_and_stroke( ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) def draw_markers(self, gc, marker_path, marker_trans, path, transform, rgbFace=None): # docstring inherited ctx = gc.ctx ctx.new_path() # Create the path for the marker; it needs to be flipped here already! _append_path(ctx, marker_path, marker_trans + Affine2D().scale(1, -1)) marker_path = ctx.copy_path_flat() # Figure out whether the path has a fill x1, y1, x2, y2 = ctx.fill_extents() if x1 == 0 and y1 == 0 and x2 == 0 and y2 == 0: filled = False # No fill, just unset this (so we don't try to fill it later on) rgbFace = None else: filled = True transform = (transform + Affine2D().scale(1, -1).translate(0, self.height)) ctx.new_path() for i, (vertices, codes) in enumerate( path.iter_segments(transform, simplify=False)): if len(vertices): x, y = vertices[-2:] ctx.save() # Translate and apply path ctx.translate(x, y) ctx.append_path(marker_path) ctx.restore() # Slower code path if there is a fill; we need to draw # the fill and stroke for each marker at the same time. # Also flush out the drawing every once in a while to # prevent the paths from getting way too long. if filled or i % 1000 == 0: self._fill_and_stroke( ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) # Fast path, if there is no fill, draw everything in one step if not filled: self._fill_and_stroke( ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) def draw_image(self, gc, x, y, im): im = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(im[::-1]) surface = cairo.ImageSurface.create_for_data( im.ravel().data, cairo.FORMAT_ARGB32, im.shape[1], im.shape[0], im.shape[1] * 4) ctx = gc.ctx y = self.height - y - im.shape[0] ctx.save() ctx.set_source_surface(surface, float(x), float(y)) ctx.paint() ctx.restore() def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): # docstring inherited # Note: (x, y) are device/display coords, not user-coords, unlike other # draw_* methods if ismath: self._draw_mathtext(gc, x, y, s, prop, angle) else: ctx = gc.ctx ctx.new_path() ctx.move_to(x, y) ctx.save() ctx.select_font_face(*_cairo_font_args_from_font_prop(prop)) ctx.set_font_size(prop.get_size_in_points() * self.dpi / 72) opts = cairo.FontOptions() opts.set_antialias( cairo.ANTIALIAS_DEFAULT if mpl.rcParams["text.antialiased"] else cairo.ANTIALIAS_NONE) ctx.set_font_options(opts) if angle: ctx.rotate(np.deg2rad(-angle)) ctx.show_text(s) ctx.restore() def _draw_mathtext(self, gc, x, y, s, prop, angle): ctx = gc.ctx width, height, descent, glyphs, rects = \ self._text2path.mathtext_parser.parse(s, self.dpi, prop) ctx.save() ctx.translate(x, y) if angle: ctx.rotate(np.deg2rad(-angle)) for font, fontsize, idx, ox, oy in glyphs: ctx.new_path() ctx.move_to(ox, -oy) ctx.select_font_face( *_cairo_font_args_from_font_prop(ttfFontProperty(font))) ctx.set_font_size(fontsize * self.dpi / 72) ctx.show_text(chr(idx)) for ox, oy, w, h in rects: ctx.new_path() ctx.rectangle(ox, -oy, w, -h) ctx.set_source_rgb(0, 0, 0) ctx.fill_preserve() ctx.restore() def get_canvas_width_height(self): # docstring inherited return self.width, self.height def get_text_width_height_descent(self, s, prop, ismath): # docstring inherited if ismath == 'TeX': return super().get_text_width_height_descent(s, prop, ismath) if ismath: width, height, descent, *_ = \ self._text2path.mathtext_parser.parse(s, self.dpi, prop) return width, height, descent ctx = self.text_ctx # problem - scale remembers last setting and font can become # enormous causing program to crash # save/restore prevents the problem ctx.save() ctx.select_font_face(*_cairo_font_args_from_font_prop(prop)) # Cairo (says it) uses 1/96 inch user space units, ref: cairo_gstate.c # but if /96.0 is used the font is too small ctx.set_font_size(prop.get_size_in_points() * self.dpi / 72) y_bearing, w, h = ctx.text_extents(s)[1:4] ctx.restore() return w, h, h + y_bearing def new_gc(self): # docstring inherited self.gc.ctx.save() self.gc._alpha = 1 self.gc._forced_alpha = False # if True, _alpha overrides A from RGBA return self.gc def points_to_pixels(self, points): # docstring inherited return points / 72 * self.dpi
def __init__(self): self.mathtext_parser = MathTextParser('path') self._texmanager = None
_("Green"): "green", _("Red"): "red", _("Yellow"): "yellow", _("Cyan"): "cyan", _("Magenta"): "magenta", _("Grey"): "grey", _("Orange"): "orange", } # --- latex (optional): insertion of latex formulas via matplotlib try: from matplotlib import rc rc('text', usetex=True) from matplotlib.mathtext import MathTextParser from matplotlib.image import imsave parser = MathTextParser('bitmap') LATEX = True except ImportError: LATEX = False def math_to_image(latex, image_path, **options): img = parser.to_rgba(latex, **options)[0] imsave(image_path, img) # --- filebrowser ZENITY = False paths = os.environ['PATH'].split(":") for path in paths:
def mathtext_parser(self): return MathTextParser("PS")
class RendererPS(_backend_pdf_ps.RendererPDFPSBase): """ The renderer handles all the drawing primitives using a graphics context instance that controls the colors/styles. """ _afm_font_dir = cbook._get_data_path("fonts/afm") _use_afm_rc_name = "ps.useafm" mathtext_parser = _api.deprecated("3.4")( property(lambda self: MathTextParser("PS"))) def __init__(self, width, height, pswriter, imagedpi=72): # Although postscript itself is dpi independent, we need to inform the # image code about a requested dpi to generate high resolution images # and them scale them before embedding them. super().__init__(width, height) self._pswriter = pswriter if mpl.rcParams['text.usetex']: self.textcnt = 0 self.psfrag = [] self.imagedpi = imagedpi # current renderer state (None=uninitialised) self.color = None self.linewidth = None self.linejoin = None self.linecap = None self.linedash = None self.fontname = None self.fontsize = None self._hatches = {} self.image_magnification = imagedpi / 72 self._clip_paths = {} self._path_collection_id = 0 self._character_tracker = _backend_pdf_ps.CharacterTracker() def set_color(self, r, g, b, store=True): if (r, g, b) != self.color: if r == g and r == b: self._pswriter.write("%1.3f setgray\n" % r) else: self._pswriter.write("%1.3f %1.3f %1.3f setrgbcolor\n" % (r, g, b)) if store: self.color = (r, g, b) def set_linewidth(self, linewidth, store=True): linewidth = float(linewidth) if linewidth != self.linewidth: self._pswriter.write("%1.3f setlinewidth\n" % linewidth) if store: self.linewidth = linewidth @staticmethod def _linejoin_cmd(linejoin): # Support for directly passing integer values is for backcompat. linejoin = { 'miter': 0, 'round': 1, 'bevel': 2, 0: 0, 1: 1, 2: 2 }[linejoin] return f"{linejoin:d} setlinejoin\n" def set_linejoin(self, linejoin, store=True): if linejoin != self.linejoin: self._pswriter.write(self._linejoin_cmd(linejoin)) if store: self.linejoin = linejoin @staticmethod def _linecap_cmd(linecap): # Support for directly passing integer values is for backcompat. linecap = { 'butt': 0, 'round': 1, 'projecting': 2, 0: 0, 1: 1, 2: 2 }[linecap] return f"{linecap:d} setlinecap\n" def set_linecap(self, linecap, store=True): if linecap != self.linecap: self._pswriter.write(self._linecap_cmd(linecap)) if store: self.linecap = linecap def set_linedash(self, offset, seq, store=True): if self.linedash is not None: oldo, oldseq = self.linedash if np.array_equal(seq, oldseq) and oldo == offset: return if seq is not None and len(seq): s = "[%s] %d setdash\n" % (_nums_to_str(*seq), offset) self._pswriter.write(s) else: self._pswriter.write("[] 0 setdash\n") if store: self.linedash = (offset, seq) def set_font(self, fontname, fontsize, store=True): if (fontname, fontsize) != (self.fontname, self.fontsize): self._pswriter.write(f"/{fontname} {fontsize:1.3f} selectfont\n") if store: self.fontname = fontname self.fontsize = fontsize def create_hatch(self, hatch): sidelen = 72 if hatch in self._hatches: return self._hatches[hatch] name = 'H%d' % len(self._hatches) linewidth = mpl.rcParams['hatch.linewidth'] pageheight = self.height * 72 self._pswriter.write(f"""\ << /PatternType 1 /PaintType 2 /TilingType 2 /BBox[0 0 {sidelen:d} {sidelen:d}] /XStep {sidelen:d} /YStep {sidelen:d} /PaintProc {{ pop {linewidth:f} setlinewidth {self._convert_path( Path.hatch(hatch), Affine2D().scale(sidelen), simplify=False)} gsave fill grestore stroke }} bind >> matrix 0.0 {pageheight:f} translate makepattern /{name} exch def """) self._hatches[hatch] = name return name def get_image_magnification(self): """ Get the factor by which to magnify images passed to draw_image. Allows a backend to have images at a different resolution to other artists. """ return self.image_magnification def _convert_path(self, path, transform, clip=False, simplify=None): if clip: clip = (0.0, 0.0, self.width * 72.0, self.height * 72.0) else: clip = None return _path.convert_to_string(path, transform, clip, simplify, None, 6, [b"m", b"l", b"", b"c", b"cl"], True).decode("ascii") def _get_clip_cmd(self, gc): clip = [] rect = gc.get_clip_rectangle() if rect is not None: clip.append("%s clipbox\n" % _nums_to_str(*rect.size, *rect.p0)) path, trf = gc.get_clip_path() if path is not None: key = (path, id(trf)) custom_clip_cmd = self._clip_paths.get(key) if custom_clip_cmd is None: custom_clip_cmd = "c%x" % len(self._clip_paths) self._pswriter.write(f"""\ /{custom_clip_cmd} {{ {self._convert_path(path, trf, simplify=False)} clip newpath }} bind def """) self._clip_paths[key] = custom_clip_cmd clip.append(f"{custom_clip_cmd}\n") return "".join(clip) def draw_image(self, gc, x, y, im, transform=None): # docstring inherited h, w = im.shape[:2] imagecmd = "false 3 colorimage" data = im[::-1, :, :3] # Vertically flipped rgb values. # data.tobytes().hex() has no spaces, so can be linewrapped by simply # splitting data every nchars. It's equivalent to textwrap.fill only # much faster. nchars = 128 data = data.tobytes().hex() hexlines = "\n".join([ data[n * nchars:(n + 1) * nchars] for n in range(math.ceil(len(data) / nchars)) ]) if transform is None: matrix = "1 0 0 1 0 0" xscale = w / self.image_magnification yscale = h / self.image_magnification else: matrix = " ".join(map(str, transform.frozen().to_values())) xscale = 1.0 yscale = 1.0 self._pswriter.write(f"""\ gsave {self._get_clip_cmd(gc)} {x:f} {y:f} translate [{matrix}] concat {xscale:f} {yscale:f} scale /DataString {w:d} string def {w:d} {h:d} 8 [ {w:d} 0 0 -{h:d} 0 {h:d} ] {{ currentfile DataString readhexstring pop }} bind {imagecmd} {hexlines} grestore """) def draw_path(self, gc, path, transform, rgbFace=None): # docstring inherited clip = rgbFace is None and gc.get_hatch_path() is None simplify = path.should_simplify and clip ps = self._convert_path(path, transform, clip=clip, simplify=simplify) self._draw_ps(ps, gc, rgbFace) def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): # docstring inherited if debugPS: self._pswriter.write('% draw_markers \n') ps_color = (None if _is_transparent(rgbFace) else '%1.3f setgray' % rgbFace[0] if rgbFace[0] == rgbFace[1] == rgbFace[2] else '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace[:3]) # construct the generic marker command: # don't want the translate to be global ps_cmd = ['/o {', 'gsave', 'newpath', 'translate'] lw = gc.get_linewidth() alpha = (gc.get_alpha() if gc.get_forced_alpha() or len(gc.get_rgb()) == 3 else gc.get_rgb()[3]) stroke = lw > 0 and alpha > 0 if stroke: ps_cmd.append('%.1f setlinewidth' % lw) ps_cmd.append(self._linejoin_cmd(gc.get_joinstyle())) ps_cmd.append(self._linecap_cmd(gc.get_capstyle())) ps_cmd.append( self._convert_path(marker_path, marker_trans, simplify=False)) if rgbFace: if stroke: ps_cmd.append('gsave') if ps_color: ps_cmd.extend([ps_color, 'fill']) if stroke: ps_cmd.append('grestore') if stroke: ps_cmd.append('stroke') ps_cmd.extend(['grestore', '} bind def']) for vertices, code in path.iter_segments(trans, clip=(0, 0, self.width * 72, self.height * 72), simplify=False): if len(vertices): x, y = vertices[-2:] ps_cmd.append("%g %g o" % (x, y)) ps = '\n'.join(ps_cmd) self._draw_ps(ps, gc, rgbFace, fill=False, stroke=False) def draw_path_collection(self, gc, master_transform, paths, all_transforms, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls, offset_position): # Is the optimization worth it? Rough calculation: # cost of emitting a path in-line is # (len_path + 2) * uses_per_path # cost of definition+use is # (len_path + 3) + 3 * uses_per_path len_path = len(paths[0].vertices) if len(paths) > 0 else 0 uses_per_path = self._iter_collection_uses_per_path( paths, all_transforms, offsets, facecolors, edgecolors) should_do_optimization = \ len_path + 3 * uses_per_path + 3 < (len_path + 2) * uses_per_path if not should_do_optimization: return RendererBase.draw_path_collection( self, gc, master_transform, paths, all_transforms, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls, offset_position) path_codes = [] for i, (path, transform) in enumerate( self._iter_collection_raw_paths(master_transform, paths, all_transforms)): name = 'p%x_%x' % (self._path_collection_id, i) path_bytes = self._convert_path(path, transform, simplify=False) self._pswriter.write(f"""\ /{name} {{ newpath translate {path_bytes} }} bind def """) path_codes.append(name) for xo, yo, path_id, gc0, rgbFace in self._iter_collection( gc, master_transform, all_transforms, path_codes, offsets, offsetTrans, facecolors, edgecolors, linewidths, linestyles, antialiaseds, urls, offset_position): ps = "%g %g %s" % (xo, yo, path_id) self._draw_ps(ps, gc0, rgbFace) self._path_collection_id += 1 def draw_tex(self, gc, x, y, s, prop, angle, *, mtext=None): # docstring inherited if not hasattr(self, "psfrag"): _log.warning( "The PS backend determines usetex status solely based on " "rcParams['text.usetex'] and does not support having " "usetex=True only for some elements; this element will thus " "be rendered as if usetex=False.") self.draw_text(gc, x, y, s, prop, angle, False, mtext) return w, h, bl = self.get_text_width_height_descent(s, prop, ismath="TeX") fontsize = prop.get_size_in_points() thetext = 'psmarker%d' % self.textcnt color = '%1.3f,%1.3f,%1.3f' % gc.get_rgb()[:3] fontcmd = { 'sans-serif': r'{\sffamily %s}', 'monospace': r'{\ttfamily %s}' }.get(mpl.rcParams['font.family'][0], r'{\rmfamily %s}') s = fontcmd % s tex = r'\color[rgb]{%s} %s' % (color, s) # Stick to the bottom alignment. pos = _nums_to_str(x, y - bl) self.psfrag.append(r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}' % (thetext, angle, fontsize, fontsize * 1.25, tex)) self._pswriter.write(f"""\ gsave {pos} moveto ({thetext}) show grestore """) self.textcnt += 1 def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): # docstring inherited if debugPS: self._pswriter.write("% text\n") if _is_transparent(gc.get_rgb()): return # Special handling for fully transparent. if ismath == 'TeX': return self.draw_tex(gc, x, y, s, prop, angle) if ismath: return self.draw_mathtext(gc, x, y, s, prop, angle) if mpl.rcParams['ps.useafm']: font = self._get_font_afm(prop) scale = 0.001 * prop.get_size_in_points() thisx = 0 last_name = None # kerns returns 0 for None. xs_names = [] for c in s: name = uni2type1.get(ord(c), f"uni{ord(c):04X}") try: width = font.get_width_from_char_name(name) except KeyError: name = 'question' width = font.get_width_char('?') kern = font.get_kern_dist_from_name(last_name, name) last_name = name thisx += kern * scale xs_names.append((thisx, name)) thisx += width * scale else: font = self._get_font_ttf(prop) font.set_text(s, 0, flags=LOAD_NO_HINTING) self._character_tracker.track(font, s) xs_names = [(item.x, font.get_glyph_name(item.glyph_idx)) for item in _text_helpers.layout(s, font)] self.set_color(*gc.get_rgb()) ps_name = (font.postscript_name.encode("ascii", "replace").decode("ascii")) self.set_font(ps_name, prop.get_size_in_points()) thetext = "\n".join(f"{x:f} 0 m /{name:s} glyphshow" for x, name in xs_names) self._pswriter.write(f"""\ gsave {self._get_clip_cmd(gc)} {x:f} {y:f} translate {angle:f} rotate {thetext} grestore """) def draw_mathtext(self, gc, x, y, s, prop, angle): """Draw the math text using matplotlib.mathtext.""" if debugPS: self._pswriter.write("% mathtext\n") width, height, descent, glyphs, rects = \ self._text2path.mathtext_parser.parse( s, 72, prop, _force_standard_ps_fonts=mpl.rcParams["ps.useafm"]) self.set_color(*gc.get_rgb()) self._pswriter.write(f"gsave\n" f"{x:f} {y:f} translate\n" f"{angle:f} rotate\n") lastfont = None for font, fontsize, num, ox, oy in glyphs: self._character_tracker.track(font, chr(num)) if (font.postscript_name, fontsize) != lastfont: lastfont = font.postscript_name, fontsize self._pswriter.write( f"/{font.postscript_name} {fontsize} selectfont\n") symbol_name = (font.get_name_char(chr(num)) if isinstance( font, AFM) else font.get_glyph_name(font.get_char_index(num))) self._pswriter.write(f"{ox:f} {oy:f} moveto\n" f"/{symbol_name} glyphshow\n") for ox, oy, w, h in rects: self._pswriter.write(f"{ox} {oy} {w} {h} rectfill\n") self._pswriter.write("grestore\n") def draw_gouraud_triangle(self, gc, points, colors, trans): self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), colors.reshape((1, 3, 4)), trans) def draw_gouraud_triangles(self, gc, points, colors, trans): assert len(points) == len(colors) assert points.ndim == 3 assert points.shape[1] == 3 assert points.shape[2] == 2 assert colors.ndim == 3 assert colors.shape[1] == 3 assert colors.shape[2] == 4 shape = points.shape flat_points = points.reshape((shape[0] * shape[1], 2)) flat_points = trans.transform(flat_points) flat_colors = colors.reshape((shape[0] * shape[1], 4)) points_min = np.min(flat_points, axis=0) - (1 << 12) points_max = np.max(flat_points, axis=0) + (1 << 12) factor = np.ceil((2**32 - 1) / (points_max - points_min)) xmin, ymin = points_min xmax, ymax = points_max streamarr = np.empty(shape[0] * shape[1], dtype=[('flags', 'u1'), ('points', '2>u4'), ('colors', '3u1')]) streamarr['flags'] = 0 streamarr['points'] = (flat_points - points_min) * factor streamarr['colors'] = flat_colors[:, :3] * 255.0 stream = quote_ps_string(streamarr.tobytes()) self._pswriter.write(f"""\ gsave << /ShadingType 4 /ColorSpace [/DeviceRGB] /BitsPerCoordinate 32 /BitsPerComponent 8 /BitsPerFlag 8 /AntiAlias true /Decode [ {xmin:f} {xmax:f} {ymin:f} {ymax:f} 0 1 0 1 0 1 ] /DataSource ({stream}) >> shfill grestore """) def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None): """ Emit the PostScript snippet 'ps' with all the attributes from 'gc' applied. 'ps' must consist of PostScript commands to construct a path. The fill and/or stroke kwargs can be set to False if the 'ps' string already includes filling and/or stroking, in which case _draw_ps is just supplying properties and clipping. """ # local variable eliminates all repeated attribute lookups write = self._pswriter.write if debugPS and command: write("% " + command + "\n") mightstroke = (gc.get_linewidth() > 0 and not _is_transparent(gc.get_rgb())) if not mightstroke: stroke = False if _is_transparent(rgbFace): fill = False hatch = gc.get_hatch() if mightstroke: self.set_linewidth(gc.get_linewidth()) self.set_linejoin(gc.get_joinstyle()) self.set_linecap(gc.get_capstyle()) self.set_linedash(*gc.get_dashes()) self.set_color(*gc.get_rgb()[:3]) write('gsave\n') write(self._get_clip_cmd(gc)) # Jochen, is the strip necessary? - this could be a honking big string write(ps.strip()) write("\n") if fill: if stroke or hatch: write("gsave\n") self.set_color(*rgbFace[:3], store=False) write("fill\n") if stroke or hatch: write("grestore\n") if hatch: hatch_name = self.create_hatch(hatch) write("gsave\n") write("%f %f %f " % gc.get_hatch_color()[:3]) write("%s setpattern fill grestore\n" % hatch_name) if stroke: write("stroke\n") write("grestore\n")
def mathtext_parser(self): return MathTextParser('SVG')
matplotlib.use("WxAgg") from numpy import arange, sin, pi, cos, log from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wx import NavigationToolbar2Wx from matplotlib.figure import Figure import wx IS_GTK = 'wxGTK' in wx.PlatformInfo IS_WIN = 'wxMSW' in wx.PlatformInfo IS_MAC = 'wxMac' in wx.PlatformInfo ############################################################ # This is where the "magic" happens. from matplotlib.mathtext import MathTextParser mathtext_parser = MathTextParser("Bitmap") def mathtext_to_wxbitmap(s): ftimage, depth = mathtext_parser.parse(s, 150) return wx.BitmapFromBufferRGBA(ftimage.get_width(), ftimage.get_height(), ftimage.as_rgba_str()) ############################################################ functions = [(r'$\sin(2 \pi x)$', lambda x: sin(2 * pi * x)), (r'$\frac{4}{3}\pi x^3$', lambda x: (4.0 / 3.0) * pi * x**3), (r'$\cos(2 \pi x)$', lambda x: cos(2 * pi * x)), (r'$\log(x)$', lambda x: log(x))]
def mathtext_parser(self): return MathTextParser('Cairo')