rst2pdf中图片的处理
一般情况下,使用 reStructuredText(ReST) 生成 PDF 格式的文件需要先转化成 LaTeX 格式。而 rst2pdf 通过调用 reportlab 工具包直接生成 PDF 文件。
配置文件
rst2pdf 会读取配置文件 (如果存在)/etc/rst2pdf.conf 和 ~/.rst2pdf/config ,也可以通过命令参数 --config=FILE 来设置配置文件的路径。配置文件的格式如下: [general]
# Footnote backlinks enabled or not (default: enabled)
footnote_backlinks=True
# Show footnotes inline instead of at the end of the document
inline_footnotes=False
配置文件的选项可以从 rst2pdf 命令选项中得到,从源代码 createpdf.py 文件 parse_commandline() 方法中就可以看出配置文件的作用是设定默认值:
def_footnote_backlinks = config.getValue("general",
"footnote_backlinks", True)
parser.add_option('--no-footnote-backlinks', action='store_false',
dest='footnote_backlinks', default=def_footnote_backlinks,
help='Disable footnote backlinks.'\
' Default=%s' % str(not def_footnote_backlinks))
图片处理
rst2pdf 是通过 PIL (Python Imaging Library)来处理图片。图片宽和高的单位可以使用 em ex px in cm mm pt pc % 或者什么都不写,默认的单位是 px 。rst2pdf 默认是300 dpi,但是可以通过命令选项 --default-dpi 或者在配置文件中设置。但是命令参数 --default-dpi 也并不是万能的,图片后缀的不同,图片的大小最后也不同。 --default-dpi 的值是通过 createpdf.py 文件传给了 style.py 文件中的类StyleSheet的属性def_dpi如下:def_dpi = config.getValue("general", "default_dpi", 300)
parser.add_option('--default-dpi', dest='def_dpi', metavar='NUMBER',
default=def_dpi,
help='DPI for objects sized in pixels. Default=%d'%def_dpi)
......
self.styles = sty.StyleSheet(styleSheets,
self.font_path,
self.style_path,
def_dpi=self.def_dpi)
命令选项 --default-dpi 的值赋予xdpi,ydpi,但是根据图片后缀的不同又将进一步变化。
xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi # 赋值
extension = imgname.split('.')[-1].lower() # 后缀
if extension in ['svg','svgz'] and SVGImage.available():
iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0)
iw = iw * xdpi / 72
ih = ih * ydpi / 72
elif extension in ["ai", "ccx", "cdr", "cgm", "cmx",
"sk1", "sk", "xml", "wmf", "fig"] and VectorImage.available():
iw, ih = VectorImage(imgname, srcinfo=srcinfo).wrap(0, 0)
iw = iw * xdpi / 72
ih = ih * ydpi / 72
......
else:
keeptrying = True
if LazyImports.PILImage:
try:
img = LazyImports.PILImage.open(imgname)
img.load()
iw, ih = img.size
xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi))
keeptrying = False
......
图片处理中 ydpi xdpi 的值我们可以通过以下代码来验证,在 image.py 380行代码出加入 print xdpi,ydpi。如果图片后缀是 gif,则与 --default-dpi 相同,后缀是 png ,则返回 72,72。
w = node.get('width')
h = node.get('height')
print xdpi,ydpi
以上代码中出现的iw,ih表示图片原宽和原高,w,h,scale是从ReST文档中得到的数值。
iw = img.size().width()
ih = img.size().height()
w = node.get('width')
h = node.get('height')
scale = float(node.get('scale', 100))/100
最后图片通过以下几种情况的处理,就会得到最后的宽和高:
- 如果 w,h 都为none,则 w = iw*inch/xdpi h = ih*inch/ydpi。
- 如果w,h 都不为 none, 则w = client.styles.adjustUnits(w, client.styles.tw,default_unit='px') h = client.styles.adjustUnits(h, ih*inch/ydpi, default_unit='px')。
- 如果 w,h 只有一个为 none,则会通过 iw/ih 来得到另一个。
- scale的默认值为100%,最后的宽和高都会乘以scale,即w = w*scale h = h*scale。