AZW3 Input: Add support for page-progression-direction

AZW3 Input: Add support for the page-progression-direction that is used
to indicate page turns should happen from right to left. The attribute
is passed into EPUB when converting. Fixes #1194766 [Incorrect conversion japanese MOBI](https://bugs.launchpad.net/calibre/+bug/1194766)
This commit is contained in:
Kovid Goyal 2013-06-26 15:46:41 +05:30
parent 03452d2a03
commit 63d133ea5c
5 changed files with 36 additions and 4 deletions

View File

@ -1047,6 +1047,14 @@ class OPF(object): # {{{
if raw:
return raw.rpartition(':')[-1]
@property
def page_progression_direction(self):
spine = self.XPath('descendant::*[re:match(name(), "spine", "i")][1]')(self.root)
if spine:
for k, v in spine[0].attrib.iteritems():
if k == 'page-progression-direction' or k.endswith('}page-progression-direction'):
return v
def guess_cover(self):
'''
Try to guess a cover. Needed for some old/badly formed OPF files.
@ -1185,6 +1193,7 @@ class OPFCreator(Metadata):
'''
Metadata.__init__(self, title='', other=other)
self.base_path = os.path.abspath(base_path)
self.page_progression_direction = None
if self.application_id is None:
self.application_id = str(uuid.uuid4())
if not isinstance(self.toc, TOC):
@ -1356,6 +1365,8 @@ class OPFCreator(Metadata):
spine = E.spine()
if self.toc is not None:
spine.set('toc', 'ncx')
if self.page_progression_direction is not None:
spine.set('page-progression-direction', self.page_progression_direction)
if self.spine is not None:
for ref in self.spine:
if ref.id is not None:

View File

@ -20,7 +20,7 @@ from calibre.ebooks.mobi.reader.ncx import read_ncx, build_toc
from calibre.ebooks.mobi.reader.markup import expand_mobi8_markup
from calibre.ebooks.metadata.opf2 import Guide, OPFCreator
from calibre.ebooks.metadata.toc import TOC
from calibre.ebooks.mobi.utils import read_font_record
from calibre.ebooks.mobi.utils import read_font_record, read_resc_record
from calibre.ebooks.oeb.parse_utils import parse_html
from calibre.ebooks.oeb.base import XPath, XHTML, xml2text
from calibre.utils.imghdr import what
@ -65,6 +65,7 @@ class Mobi8Reader(object):
self.mobi6_reader, self.log = mobi6_reader, log
self.header = mobi6_reader.book_header
self.encrypted_fonts = []
self.resc_data = {}
def __call__(self):
self.mobi6_reader.check_for_drm()
@ -389,9 +390,11 @@ class Mobi8Reader(object):
data = sec[0]
typ = data[:4]
href = None
if typ in {b'FLIS', b'FCIS', b'SRCS', b'\xe9\x8e\r\n',
b'RESC', b'BOUN', b'FDST', b'DATP', b'AUDI', b'VIDE'}:
if typ in {b'FLIS', b'FCIS', b'SRCS', b'\xe9\x8e\r\n', b'BOUN',
b'FDST', b'DATP', b'AUDI', b'VIDE'}:
pass # Ignore these records
elif typ == b'RESC':
self.resc_data = read_resc_record(data)
elif typ == b'FONT':
font = read_font_record(data)
href = "fonts/%05d.%s" % (fname_idx, font['ext'])
@ -452,6 +455,9 @@ class Mobi8Reader(object):
opf.create_manifest_from_files_in([os.getcwdu()], exclude=exclude)
opf.create_spine(spine)
opf.set_toc(toc)
ppd = self.resc_data.get('page-progression-direction', None)
if ppd:
opf.page_progression_direction = ppd
with open('metadata.opf', 'wb') as of, open('toc.ncx', 'wb') as ncx:
opf.render(of, ncx, 'toc.ncx')

View File

@ -7,7 +7,7 @@ __license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import struct, string, zlib, os
import struct, string, zlib, os, re
from collections import OrderedDict
from io import BytesIO
@ -393,6 +393,15 @@ def mobify_image(data):
data = im.export('gif')
return data
def read_resc_record(data):
ans = {}
match = re.search(br'''<spine [^>]*page-progression-direction=['"](.+?)['"]''', data)
if match is not None:
ppd = match.group(1).lower()
if ppd in {b'ltr', b'rtl'}:
ans['page-progression-direction'] = ppd.decode('ascii')
return ans
# Font records {{{
def read_font_record(data, extent=1040):
'''

View File

@ -1210,6 +1210,7 @@ class Spine(object):
def __init__(self, oeb):
self.oeb = oeb
self.items = []
self.page_progression_direction = None
def _linear(self, linear):
if isinstance(linear, basestring):
@ -1896,4 +1897,6 @@ class OEBBook(object):
attrib={'media-type': PAGE_MAP_MIME})
spine.attrib['page-map'] = id
results[PAGE_MAP_MIME] = (href, self.pages.to_page_map())
if self.spine.page_progression_direction in {'ltr', 'rtl'}:
spine.attrib['page-progression-direction'] = self.spine.page_progression_direction
return results

View File

@ -330,6 +330,9 @@ class OEBReader(object):
if len(spine) == 0:
raise OEBError("Spine is empty")
self._spine_add_extra()
for val in xpath(opf, '/o2:package/o2:spine/@page-progression-direction'):
if val in {'ltr', 'rtl'}:
spine.page_progression_direction = val
def _guide_from_opf(self, opf):
guide = self.oeb.guide