mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
parent
03452d2a03
commit
63d133ea5c
@ -1047,6 +1047,14 @@ class OPF(object): # {{{
|
|||||||
if raw:
|
if raw:
|
||||||
return raw.rpartition(':')[-1]
|
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):
|
def guess_cover(self):
|
||||||
'''
|
'''
|
||||||
Try to guess a cover. Needed for some old/badly formed OPF files.
|
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)
|
Metadata.__init__(self, title='', other=other)
|
||||||
self.base_path = os.path.abspath(base_path)
|
self.base_path = os.path.abspath(base_path)
|
||||||
|
self.page_progression_direction = None
|
||||||
if self.application_id is None:
|
if self.application_id is None:
|
||||||
self.application_id = str(uuid.uuid4())
|
self.application_id = str(uuid.uuid4())
|
||||||
if not isinstance(self.toc, TOC):
|
if not isinstance(self.toc, TOC):
|
||||||
@ -1356,6 +1365,8 @@ class OPFCreator(Metadata):
|
|||||||
spine = E.spine()
|
spine = E.spine()
|
||||||
if self.toc is not None:
|
if self.toc is not None:
|
||||||
spine.set('toc', 'ncx')
|
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:
|
if self.spine is not None:
|
||||||
for ref in self.spine:
|
for ref in self.spine:
|
||||||
if ref.id is not None:
|
if ref.id is not None:
|
||||||
|
@ -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.mobi.reader.markup import expand_mobi8_markup
|
||||||
from calibre.ebooks.metadata.opf2 import Guide, OPFCreator
|
from calibre.ebooks.metadata.opf2 import Guide, OPFCreator
|
||||||
from calibre.ebooks.metadata.toc import TOC
|
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.parse_utils import parse_html
|
||||||
from calibre.ebooks.oeb.base import XPath, XHTML, xml2text
|
from calibre.ebooks.oeb.base import XPath, XHTML, xml2text
|
||||||
from calibre.utils.imghdr import what
|
from calibre.utils.imghdr import what
|
||||||
@ -65,6 +65,7 @@ class Mobi8Reader(object):
|
|||||||
self.mobi6_reader, self.log = mobi6_reader, log
|
self.mobi6_reader, self.log = mobi6_reader, log
|
||||||
self.header = mobi6_reader.book_header
|
self.header = mobi6_reader.book_header
|
||||||
self.encrypted_fonts = []
|
self.encrypted_fonts = []
|
||||||
|
self.resc_data = {}
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
self.mobi6_reader.check_for_drm()
|
self.mobi6_reader.check_for_drm()
|
||||||
@ -389,9 +390,11 @@ class Mobi8Reader(object):
|
|||||||
data = sec[0]
|
data = sec[0]
|
||||||
typ = data[:4]
|
typ = data[:4]
|
||||||
href = None
|
href = None
|
||||||
if typ in {b'FLIS', b'FCIS', b'SRCS', b'\xe9\x8e\r\n',
|
if typ in {b'FLIS', b'FCIS', b'SRCS', b'\xe9\x8e\r\n', b'BOUN',
|
||||||
b'RESC', b'BOUN', b'FDST', b'DATP', b'AUDI', b'VIDE'}:
|
b'FDST', b'DATP', b'AUDI', b'VIDE'}:
|
||||||
pass # Ignore these records
|
pass # Ignore these records
|
||||||
|
elif typ == b'RESC':
|
||||||
|
self.resc_data = read_resc_record(data)
|
||||||
elif typ == b'FONT':
|
elif typ == b'FONT':
|
||||||
font = read_font_record(data)
|
font = read_font_record(data)
|
||||||
href = "fonts/%05d.%s" % (fname_idx, font['ext'])
|
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_manifest_from_files_in([os.getcwdu()], exclude=exclude)
|
||||||
opf.create_spine(spine)
|
opf.create_spine(spine)
|
||||||
opf.set_toc(toc)
|
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:
|
with open('metadata.opf', 'wb') as of, open('toc.ncx', 'wb') as ncx:
|
||||||
opf.render(of, ncx, 'toc.ncx')
|
opf.render(of, ncx, 'toc.ncx')
|
||||||
|
@ -7,7 +7,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import struct, string, zlib, os
|
import struct, string, zlib, os, re
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
@ -393,6 +393,15 @@ def mobify_image(data):
|
|||||||
data = im.export('gif')
|
data = im.export('gif')
|
||||||
return data
|
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 {{{
|
# Font records {{{
|
||||||
def read_font_record(data, extent=1040):
|
def read_font_record(data, extent=1040):
|
||||||
'''
|
'''
|
||||||
|
@ -1210,6 +1210,7 @@ class Spine(object):
|
|||||||
def __init__(self, oeb):
|
def __init__(self, oeb):
|
||||||
self.oeb = oeb
|
self.oeb = oeb
|
||||||
self.items = []
|
self.items = []
|
||||||
|
self.page_progression_direction = None
|
||||||
|
|
||||||
def _linear(self, linear):
|
def _linear(self, linear):
|
||||||
if isinstance(linear, basestring):
|
if isinstance(linear, basestring):
|
||||||
@ -1896,4 +1897,6 @@ class OEBBook(object):
|
|||||||
attrib={'media-type': PAGE_MAP_MIME})
|
attrib={'media-type': PAGE_MAP_MIME})
|
||||||
spine.attrib['page-map'] = id
|
spine.attrib['page-map'] = id
|
||||||
results[PAGE_MAP_MIME] = (href, self.pages.to_page_map())
|
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
|
return results
|
||||||
|
@ -330,6 +330,9 @@ class OEBReader(object):
|
|||||||
if len(spine) == 0:
|
if len(spine) == 0:
|
||||||
raise OEBError("Spine is empty")
|
raise OEBError("Spine is empty")
|
||||||
self._spine_add_extra()
|
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):
|
def _guide_from_opf(self, opf):
|
||||||
guide = self.oeb.guide
|
guide = self.oeb.guide
|
||||||
|
Loading…
x
Reference in New Issue
Block a user