text: # -*- coding: utf-8 -*-
  """
      pygments.formatters.svg
      ~~~~~~~~~~~~~~~~~~~~~~~
  
      Formatter for SVG output.
  
      :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS.
      :license: BSD, see LICENSE for details.
  """
  
  from pygments.formatter import Formatter
  from pygments.util import get_bool_opt, get_int_opt
  
  __all__ = ['SvgFormatter']
  
  
  def escape_html(text):
      """Escape &, <, > as well as single and double quotes for HTML."""
      return text.replace('&', '&amp;').  \
                  replace('<', '&lt;').   \
                  replace('>', '&gt;').   \
                  replace('"', '&quot;'). \
                  replace("'", '&#39;')
  
  
  class2style = {}
  
  class SvgFormatter(Formatter):
      """
      Format tokens as an SVG graphics file.  This formatter is still experimental.
      Each line of code is a ``<text>`` element with explicit ``x`` and ``y``
      coordinates containing ``<tspan>`` elements with the individual token styles.
  
      By default, this formatter outputs a full SVG document including doctype
      declaration and the ``<svg>`` root element.
  
      *New in Pygments 0.9.*
  
      Additional options accepted:
  
      `nowrap`
          Don't wrap the SVG ``<text>`` elements in ``<svg><g>`` elements and
          don't add a XML declaration and a doctype.  If true, the `fontfamily`
          and `fontsize` options are ignored.  Defaults to ``False``.
  
      `fontfamily`
          The value to give the wrapping ``<g>`` element's ``font-family``
          attribute, defaults to ``"monospace"``.
  
      `fontsize`
          The value to give the wrapping ``<g>`` element's ``font-size``
          attribute, defaults to ``"14px"``.
  
      `xoffset`
          Starting offset in X direction, defaults to ``0``.
  
      `yoffset`
          Starting offset in Y direction, defaults to the font size if it is given
          in pixels, or ``20`` else.  (This is necessary since text coordinates
          refer to the text baseline, not the top edge.)
  
      `ystep`
          Offset to add to the Y coordinate for each subsequent line.  This should
          roughly be the text size plus 5.  It defaults to that value if the text
          size is given in pixels, or ``25`` else.
  
      `spacehack`
          Convert spaces in the source to ``&#160;``, which are non-breaking
          spaces.  SVG provides the ``xml:space`` attribute to control how
          whitespace inside tags is handled, in theory, the ``preserve`` value
          could be used to keep all whitespace as-is.  However, many current SVG
          viewers don't obey that rule, so this option is provided as a workaround
          and defaults to ``True``.
      """
      name = 'SVG'
      aliases = ['svg']
      filenames = ['*.svg']
  
      def __init__(self, **options):
          # XXX outencoding
          Formatter.__init__(self, **options)
          self.nowrap = get_bool_opt(options, 'nowrap', False)
          self.fontfamily = options.get('fontfamily', 'monospace')
          self.fontsize = options.get('fontsize', '14px')
          self.xoffset = get_int_opt(options, 'xoffset', 0)
          fs = self.fontsize.strip()
          if fs.endswith('px'): fs = fs[:-2].strip()
          try:
              int_fs = int(fs)
          except:
              int_fs = 20
          self.yoffset = get_int_opt(options, 'yoffset', int_fs)
          self.ystep = get_int_opt(options, 'ystep', int_fs + 5)
          self.spacehack = get_bool_opt(options, 'spacehack', True)
          self._stylecache = {}
  
      def format_unencoded(self, tokensource, outfile):
          """
          Format ``tokensource``, an iterable of ``(tokentype, tokenstring)``
          tuples and write it into ``outfile``.
  
          For our implementation we put all lines in their own 'line group'.
          """
          x = self.xoffset
          y = self.yoffset
          if not self.nowrap:
              if self.encoding:
                  outfile.write('<?xml version="1.0" encoding="%s"?>\n' %
                                self.encoding)
              else:
                  outfile.write('<?xml version="1.0"?>\n')
              outfile.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" '
                            '"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/'
                            'svg10.dtd">\n')
              outfile.write('<svg xmlns="http://www.w3.org/2000/svg">\n')
              outfile.write('<g font-family="%s" font-size="%s">\n' %
                            (self.fontfamily, self.fontsize))
          outfile.write('<text x="%s" y="%s" xml:space="preserve">' % (x, y))
          for ttype, value in tokensource:
              style = self._get_style(ttype)
              tspan = style and '<tspan' + style + '>' or ''
              tspanend = tspan and '</tspan>' or ''
              value = escape_html(value)
              if self.spacehack:
                  value = value.expandtabs().replace(' ', '&#160;')
              parts = value.split('\n')
              for part in parts[:-1]:
                  outfile.write(tspan + part + tspanend)
                  y += self.ystep
                  outfile.write('</text>\n<text x="%s" y="%s" '
                                'xml:space="preserve">' % (x, y))
              outfile.write(tspan + parts[-1] + tspanend)
          outfile.write('</text>')
  
          if not self.nowrap:
              outfile.write('</g></svg>\n')
  
      def _get_style(self, tokentype):
          if tokentype in self._stylecache:
              return self._stylecache[tokentype]
          otokentype = tokentype
          while not self.style.styles_token(tokentype):
              tokentype = tokentype.parent
          value = self.style.style_for_token(tokentype)
          result = ''
          if value['color']:
              result = ' fill="#' + value['color'] + '"'
          if value['bold']:
              result += ' font-weight="bold"'
          if value['italic']:
              result += ' font-style="italic"'
          self._stylecache[otokentype] = result
          return result
  