|
From: <jo...@us...> - 2007-09-10 20:31:04
|
Revision: 3827
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3827&view=rev
Author: jouni
Date: 2007-09-10 13:31:01 -0700 (Mon, 10 Sep 2007)
Log Message:
-----------
Better bounding boxes for pdf usetex, including descents.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
trunk/matplotlib/lib/matplotlib/dviread.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-10 19:25:21 UTC (rev 3826)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-10 20:31:01 UTC (rev 3827)
@@ -1427,14 +1427,14 @@
# Pop off the global transformation
self.file.output(Op.grestore)
- def _draw_tex(self, gc, x, y, s, prop, angle):
+ def draw_tex(self, gc, x, y, s, prop, angle):
# Rename to draw_tex to enable
texmanager = self.get_texmanager()
fontsize = prop.get_size_in_points()
dvifile = texmanager.make_dvi(s, fontsize)
dvi = dviread.Dvi(dvifile, 72)
- text, boxes = iter(dvi).next()
+ page = iter(dvi).next()
dvi.close()
if angle == 0: # avoid rounding errors in common case
@@ -1448,7 +1448,7 @@
# Gather font information and do some setup for combining
# characters into strings.
oldfontnum, seq = None, []
- for x1, y1, fontnum, glyph, width in text:
+ for x1, y1, fontnum, glyph, width in page.text:
if fontnum != oldfontnum:
texname, fontsize = dvi.fontinfo(fontnum)
fontinfo = self.tex_font_mapping(texname)
@@ -1462,8 +1462,8 @@
seq += [('end',)]
# Find consecutive text strings with constant x coordinate and
- # combine into one string (if needed kern would be less than
- # 0.1 points) or several strings interspersed with kerns.
+ # combine into a sequence of strings and kerns, or just one
+ # string (if any kerns would be less than 0.1 points).
i, curx = 0, 0
while i < len(seq)-1:
elt, next = seq[i:i+2]
@@ -1503,7 +1503,7 @@
boxgc = self.new_gc()
boxgc.copy_properties(gc)
boxgc.set_linewidth(0)
- for x1, y1, h, w in boxes:
+ for x1, y1, h, w in page.boxes:
(x1, y1), (x2, y2), (x3, y3), (x4, y4) = \
mytrans(x1, y1), mytrans(x1+w, y1), \
mytrans(x1+w, y1+h), mytrans(x1, y1+h)
@@ -1653,14 +1653,9 @@
fontsize = prop.get_size_in_points()
dvifile = texmanager.make_dvi(s, fontsize)
dvi = dviread.Dvi(dvifile, 72)
- text, boxes = iter(dvi).next()
- # TODO: better bounding box -- this is not quite right:
- l = min(p[0] for p in text+boxes)
- r = max(p[0] for p in text+boxes) + fontsize
- b = min(p[1] for p in text+boxes)
- t = max(p[1] for p in text+boxes) + fontsize
- # (not to even mention finding the baseline)
- return r-l, t-b, t-b
+ page = iter(dvi).next()
+ dvi.close()
+ return page.width, page.height, page.descent
if ismath:
w, h, d, glyphs, rects, used_characters = \
self.mathtext_parser.parse(s, 72, prop)
Modified: trunk/matplotlib/lib/matplotlib/dviread.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-10 19:25:21 UTC (rev 3826)
+++ trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-10 20:31:01 UTC (rev 3827)
@@ -6,19 +6,21 @@
Interface:
dvi = Dvi(filename, 72)
- for text, boxes in dvi: # iterate over pages
- text, boxes = dvi.output(72)
- for x,y,font,glyph,width in text:
+ for page in dvi: # iterate over pages
+ w, h, d = page.width, page.height, page.descent
+ for x,y,font,glyph,width in page.text:
fontname, pointsize = dvi.fontinfo(font)
...
- for x,y,height,width in boxes:
+ for x,y,height,width in page.boxes:
...
"""
-# TODO: support for TeX virtual fonts (*.vf) which are a dvi-like format
+# TODO: support TeX virtual fonts (*.vf) which are a sort of
+# subroutine collections for dvi files
import matplotlib
import matplotlib.cbook as mpl_cbook
+import numpy as npy
import os
import struct
@@ -74,21 +76,34 @@
def _output(self):
"""
Output the text and boxes belonging to the most recent page.
- text, boxes = dvi._output()
+ page = dvi._output()
"""
- t0 = self.text[0]
- minx, miny, maxx, maxy = t0[0], t0[1], t0[0], t0[1]
+ minx, miny, maxx, maxy = npy.inf, npy.inf, -npy.inf, -npy.inf
+ maxy_pure = -npy.inf
for elt in self.text + self.boxes:
- x,y = elt[:2]
- if x < minx: minx = x
- if y < miny: miny = y
- if x > maxx: maxx = x
- if y > maxy: maxy = y
+ if len(elt) == 4: # box
+ x,y,h,w = elt
+ e = 0 # zero depth
+ else: # glyph
+ x,y,f,g,w = elt
+ font = self.fonts[f]
+ h = (font.scale * font.tfm.height[g]) >> 20
+ e = (font.scale * font.tfm.depth[g]) >> 20
+ minx = min(minx, x)
+ miny = min(miny, y - h)
+ maxx = max(maxx, x + w)
+ maxy = max(maxy, y + e)
+ maxy_pure = max(maxy_pure, y)
+
d = self.dpi / (72.27 * 2**16) # from TeX's "scaled points" to dpi units
text = [ ((x-minx)*d, (maxy-y)*d, f, g, w*d) for (x,y,f,g,w) in self.text ]
boxes = [ ((x-minx)*d, (maxy-y)*d, h*d, w*d) for (x,y,h,w) in self.boxes ]
- return text, boxes
+ return mpl_cbook.Bunch(text=text, boxes=boxes,
+ width=(maxx-minx)*d,
+ height=(maxy_pure-miny)*d,
+ descent=(maxy-maxy_pure)*d)
+
def fontinfo(self, f):
"""
texname, pointsize = dvi.fontinfo(fontnum)
@@ -361,6 +376,7 @@
width[i]: width of character #i, needs to be scaled
by the factor specified in the dvi file
(this is a dict because indexing may not start from 0)
+ height[i], depth[i]: height and depth of character #i
"""
def __init__(self, filename):
@@ -368,22 +384,29 @@
try:
header1 = file.read(24)
- lh, bc, ec, nw = \
- struct.unpack('!4H', header1[2:10])
+ lh, bc, ec, nw, nh, nd = \
+ struct.unpack('!6H', header1[2:14])
header2 = file.read(4*lh)
self.checksum, self.design_size = \
struct.unpack('!2I', header2[:8])
# there is also encoding information etc.
char_info = file.read(4*(ec-bc+1))
widths = file.read(4*nw)
+ heights = file.read(4*nh)
+ depths = file.read(4*nd)
finally:
file.close()
- widths = struct.unpack('!%dI' % nw, widths)
- self.width = {}
+ self.width, self.height, self.depth = {}, {}, {}
+ widths, heights, depths = \
+ [ struct.unpack('!%dI' % n, x)
+ for n,x in [(nw, widths), (nh, heights), (nd, depths)] ]
for i in range(ec-bc):
self.width[bc+i] = widths[ord(char_info[4*i])]
+ self.height[bc+i] = heights[ord(char_info[4*i+1]) >> 4]
+ self.depth[bc+i] = depths[ord(char_info[4*i+1]) & 0xf]
+
class PsfontsMap(object):
"""
A psfonts.map formatted file, mapping TeX fonts to PS fonts.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|