Commits

Georg Brandl committed 0efbf22

#65: Store depth information in PNG images themselves.

  • Participants
  • Parent commits f0aba27

Comments (0)

Files changed (3)

 Release 0.5.1 (in development)
 ==============================
 
+* #65: Fix storage of depth information for PNGs generated by the
+  pngmath extension.
+
 * Fix autodoc crash when automethod is used outside a class context.
 
-* Fix LaTeX writer output for images with specified height.
+* #68: Fix LaTeX writer output for images with specified height.
 
-* Fix wrong generated image path when including images in sources
+* #60: Fix wrong generated image path when including images in sources
   in subdirectories.
 
 * Fix the JavaScript search when html_copy_source is off.
 Bugs fixed
 ----------
 
-* Escape configuration values placed in HTML templates.
+* #51: Escape configuration values placed in HTML templates.
 
-* Fix small problems in HTML help index generation.
+* #44: Fix small problems in HTML help index generation.
 
 * Fix LaTeX output for line blocks in tables.
 
-* Fix "illegal unit" error when using pixel image widths/heights.
+* #38: Fix "illegal unit" error when using pixel image widths/heights.
 
 * Support table captions in LaTeX output.
 
-* Work around a bug in Jinja that caused "<generator ...>" to be
+* #39: Work around a bug in Jinja that caused "<generator ...>" to be
   emitted in HTML output.
 
 * Fix a problem with module links not being generated in LaTeX output.
 
 * Fix the handling of images in different directories.
 
-* Support option lists in the text writer.  Make sure that dashes
+* #29: Support option lists in the text writer.  Make sure that dashes
   introducing long option names are not contracted to en-dashes.
 
 * Support the "scale" option for images in HTML output.
 
-* Properly escape quotes in HTML help attribute values.
+* #25: Properly escape quotes in HTML help attribute values.
 
 * Fix LaTeX build for some description environments with ``:noindex:``.
 
-* Don't crash on weird casing of role names (like ``:Class:``).
+* #24: Don't crash on uncommon casing of role names (like ``:Class:``).
 
 * Only output ANSI colors on color terminals.
 

File sphinx/ext/pngmath.py

 from docutils import nodes
 
 from sphinx.util import ensuredir
+from sphinx.util.png import read_png_depth, write_png_depth
 from sphinx.application import SphinxError
 from sphinx.ext.mathbase import setup as mathbase_setup, wrap_displaymath
 
     relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
     outfn = path.join(self.builder.outdir, '_images', 'math', shasum)
     if path.isfile(outfn):
-        return relfn, self.builder.env._pngmath_depth.get(shasum, None)
+        depth = read_png_depth(outfn)
+        return relfn, depth
 
     latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
     latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
             m = depth_re.match(line)
             if m:
                 depth = int(m.group(1))
-                self.builder.env._pngmath_depth[shasum] = depth
+                write_png_depth(outfn, depth)
                 break
 
     return relfn, depth
 
-def ensure_depthcache(app, env):
-    if not hasattr(env, '_pngmath_depth'):
-        env._pngmath_depth = {}
-
 def cleanup_tempdir(app, exc):
     if exc:
         return
     app.add_config_value('pngmath_use_preview', False, False)
     app.add_config_value('pngmath_dvipng_args', ['-gamma 1.5', '-D 110'], False)
     app.add_config_value('pngmath_latex_preamble', '', False)
-    app.connect('env-updated', ensure_depthcache)
     app.connect('build-finished', cleanup_tempdir)

File sphinx/util/png.py

+# -*- coding: utf-8 -*-
+"""
+    sphinx.util.png
+    ~~~~~~~~~~~~~~~
+
+    PNG image manipulation helpers.
+
+    :copyright: 2008 by Georg Brandl.
+    :license: BSD.
+"""
+
+import struct
+import binascii
+
+LEN_IEND = 12
+LEN_DEPTH = 22
+
+DEPTH_CHUNK_LEN = struct.pack('!i', 10)
+DEPTH_CHUNK_START = 'tEXtDepth\x00'
+IEND_CHUNK = '\x00\x00\x00\x00IEND\xAE\x42\x60\x82'
+
+
+def read_png_depth(filename):
+    """
+    Read the special tEXt chunk indicating the depth from a PNG file.
+    """
+    result = None
+    f = open(filename, 'rb')
+    try:
+        f.seek(- (LEN_IEND + LEN_DEPTH), 2)
+        depthchunk = f.read(LEN_DEPTH)
+        if not depthchunk.startswith(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START):
+            # either not a PNG file or not containing the depth chunk
+            return None
+        result = struct.unpack('!i', depthchunk[14:18])[0]
+    finally:
+        f.close()
+    return result
+
+
+def write_png_depth(filename, depth):
+    """
+    Write the special tEXt chunk indicating the depth to a PNG file.
+    The chunk is placed immediately before the special IEND chunk.
+    """
+    data = struct.pack('!i', depth)
+    f = open(filename, 'r+b')
+    try:
+        # seek to the beginning of the IEND chunk
+        f.seek(-LEN_IEND, 2)
+        # overwrite it with the depth chunk
+        f.write(DEPTH_CHUNK_LEN + DEPTH_CHUNK_START + data)
+        # calculate the checksum over chunk name and data
+        f.write(struct.pack('!i', binascii.crc32(DEPTH_CHUNK_START + data)))
+        # replace the IEND chunk
+        f.write(IEND_CHUNK)
+    finally:
+        f.close()