mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix serialization of floating point numbers
This commit is contained in:
parent
40539ca292
commit
836a623b5f
@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en'
|
||||
import codecs, zlib
|
||||
from io import BytesIO
|
||||
from struct import pack
|
||||
from decimal import Decimal
|
||||
|
||||
EOL = b'\n'
|
||||
|
||||
@ -51,13 +52,30 @@ PAPER_SIZES = {k:globals()[k.upper()] for k in ('a0 a1 a2 a3 a4 a5 a6 b0 b1 b2'
|
||||
|
||||
# Basic PDF datatypes {{{
|
||||
|
||||
def format_float(f):
|
||||
if abs(f) < 1e-7:
|
||||
return '0'
|
||||
places = 6
|
||||
a, b = type(u'')(Decimal(f).quantize(Decimal(10)**-places)).partition('.')[0::2]
|
||||
b = b.rstrip('0')
|
||||
if not b:
|
||||
return '0' if a == '-0' else a
|
||||
return '%s.%s'%(a, b)
|
||||
|
||||
def fmtnum(o):
|
||||
if isinstance(o, (int, long)):
|
||||
return type(u'')(o)
|
||||
return format_float(o)
|
||||
|
||||
def serialize(o, stream):
|
||||
if hasattr(o, 'pdf_serialize'):
|
||||
o.pdf_serialize(stream)
|
||||
elif isinstance(o, bool):
|
||||
stream.write(b'true' if o else b'false')
|
||||
elif isinstance(o, (int, long, float)):
|
||||
elif isinstance(o, (int, long)):
|
||||
stream.write(type(u'')(o).encode('ascii'))
|
||||
elif isinstance(o, float):
|
||||
stream.write(format_float(o).encode('ascii'))
|
||||
elif o is None:
|
||||
stream.write(b'null')
|
||||
else:
|
||||
|
@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en'
|
||||
import sys, traceback
|
||||
from collections import namedtuple
|
||||
from functools import wraps, partial
|
||||
from future_builtins import map
|
||||
|
||||
import sip
|
||||
from PyQt4.Qt import (QPaintEngine, QPaintDevice, Qt, QApplication, QPainter,
|
||||
@ -18,13 +19,17 @@ from PyQt4.Qt import (QPaintEngine, QPaintDevice, Qt, QApplication, QPainter,
|
||||
|
||||
from calibre.constants import plugins
|
||||
from calibre.ebooks.pdf.render.serialize import (Color, PDFStream, Path)
|
||||
from calibre.ebooks.pdf.render.common import inch, A4
|
||||
from calibre.ebooks.pdf.render.common import inch, A4, fmtnum
|
||||
from calibre.utils.fonts.sfnt.container import Sfnt
|
||||
from calibre.utils.fonts.sfnt.metrics import FontMetrics
|
||||
|
||||
Point = namedtuple('Point', 'x y')
|
||||
ColorState = namedtuple('ColorState', 'color opacity do')
|
||||
|
||||
def repr_transform(t):
|
||||
vals = map(fmtnum, (t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy()))
|
||||
return '[%s]'%' '.join(vals)
|
||||
|
||||
def store_error(func):
|
||||
|
||||
@wraps(func)
|
||||
|
@ -15,7 +15,7 @@ from collections import namedtuple
|
||||
from calibre.constants import (__appname__, __version__)
|
||||
from calibre.ebooks.pdf.render.common import (
|
||||
Reference, EOL, serialize, Stream, Dictionary, String, Name, Array,
|
||||
GlyphIndex)
|
||||
GlyphIndex, fmtnum)
|
||||
from calibre.ebooks.pdf.render.fonts import FontManager
|
||||
from calibre.ebooks.pdf.render.links import Links
|
||||
|
||||
@ -180,7 +180,7 @@ class Text(object):
|
||||
stream.write_line('BT ')
|
||||
serialize(Name(font_name), stream)
|
||||
stream.write(' %g Tf '%self.size)
|
||||
stream.write(' '.join(map(type(u''), self.transform)) + ' Tm ')
|
||||
stream.write(' '.join(map(fmtnum, self.transform)) + ' Tm ')
|
||||
if self.horizontal_scale != self.default_horizontal_scale:
|
||||
stream.write('%g Tz '%self.horizontal_scale)
|
||||
if self.word_spacing != self.default_word_spacing:
|
||||
@ -331,7 +331,7 @@ class PDFStream(object):
|
||||
vals = [m.m11(), m.m12(), m.m21(), m.m22(), m.dx(), m.dy()]
|
||||
else:
|
||||
vals = args
|
||||
cm = ' '.join(map(type(u''), vals))
|
||||
cm = ' '.join(map(fmtnum, vals))
|
||||
self.current_page.write_line(cm + ' cm')
|
||||
|
||||
def set_rgb_colorspace(self):
|
||||
@ -355,7 +355,8 @@ class PDFStream(object):
|
||||
if i != 0:
|
||||
self.current_page.write_line()
|
||||
for x in op:
|
||||
self.current_page.write(type(u'')(x) + ' ')
|
||||
self.current_page.write(
|
||||
(fmtnum(x) if isinstance(x, (int, long, float)) else x) + ' ')
|
||||
|
||||
def draw_path(self, path, stroke=True, fill=False, fill_rule='winding'):
|
||||
if not path.ops: return
|
||||
@ -394,7 +395,7 @@ class PDFStream(object):
|
||||
op = Dictionary({'Type':Name('ExtGState'), 'CA': opacity})
|
||||
self.stroke_opacities[opacity] = self.objects.add(op)
|
||||
self.current_page.set_opacity(self.stroke_opacities[opacity])
|
||||
self.current_page.write_line(' '.join(map(type(u''), color[:3])) + ' SC')
|
||||
self.current_page.write_line(' '.join(map(fmtnum, color[:3])) + ' SC')
|
||||
|
||||
def set_fill_color(self, color):
|
||||
opacity = color.opacity
|
||||
@ -402,7 +403,7 @@ class PDFStream(object):
|
||||
op = Dictionary({'Type':Name('ExtGState'), 'ca': opacity})
|
||||
self.fill_opacities[opacity] = self.objects.add(op)
|
||||
self.current_page.set_opacity(self.fill_opacities[opacity])
|
||||
self.current_page.write_line(' '.join(map(type(u''), color[:3])) + ' sc')
|
||||
self.current_page.write_line(' '.join(map(fmtnum, color[:3])) + ' sc')
|
||||
|
||||
def end_page(self):
|
||||
pageref = self.current_page.end(self.objects, self.stream)
|
||||
@ -424,7 +425,7 @@ class PDFStream(object):
|
||||
self.current_page.write(b'BT ')
|
||||
serialize(Name(name), self.current_page)
|
||||
self.current_page.write(' %g Tf '%size)
|
||||
self.current_page.write('%s Tm '%' '.join(map(type(u''), transform)))
|
||||
self.current_page.write('%s Tm '%' '.join(map(fmtnum, transform)))
|
||||
for x, y, glyph_id in glyphs:
|
||||
self.current_page.write('%g %g Td '%(x, y))
|
||||
serialize(GlyphIndex(glyph_id), self.current_page)
|
||||
|
Loading…
x
Reference in New Issue
Block a user