mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
AZW3: Preserve the primary-writing-mopde EXTH header field when round-tripping AZW3 files. Should fix editing/conversion of RTL AZW3 files causing page turning to become left-to-right on the Kindle
This commit is contained in:
parent
da8958b573
commit
5f313b64af
@ -1163,6 +1163,11 @@ class OPF(object): # {{{
|
||||
if k == 'page-progression-direction' or k.endswith('}page-progression-direction'):
|
||||
return v
|
||||
|
||||
@property
|
||||
def primary_writing_mode(self):
|
||||
for m in self.XPath('//*[local-name()="meta" and @name="primary-writing-mode" and @content]')(self.root):
|
||||
return m.get('content')
|
||||
|
||||
def guess_cover(self):
|
||||
'''
|
||||
Try to guess a cover. Needed for some old/badly formed OPF files.
|
||||
@ -1384,6 +1389,7 @@ class OPFCreator(Metadata):
|
||||
Metadata.__init__(self, title='', other=other)
|
||||
self.base_path = os.path.abspath(base_path)
|
||||
self.page_progression_direction = None
|
||||
self.primary_writing_mode = None
|
||||
if self.application_id is None:
|
||||
self.application_id = str(uuid.uuid4())
|
||||
if not isinstance(self.toc, TOC):
|
||||
@ -1546,6 +1552,8 @@ class OPFCreator(Metadata):
|
||||
from calibre.ebooks.metadata.book.json_codec import object_to_unicode
|
||||
a(CAL_ELEM('calibre:user_categories',
|
||||
json.dumps(object_to_unicode(self.user_categories))))
|
||||
if self.primary_writing_mode:
|
||||
a(M.meta(name='primary-writing-mode', content=self.primary_writing_mode))
|
||||
manifest = E.manifest()
|
||||
if self.manifest is not None:
|
||||
for ref in self.manifest:
|
||||
|
@ -34,6 +34,7 @@ class EXTHHeader(object): # {{{
|
||||
self.kf8_header = None
|
||||
self.uuid = self.cdetype = None
|
||||
self.page_progression_direction = None
|
||||
self.primary_writing_mode = None
|
||||
|
||||
self.decode = lambda x : clean_ascii_chars(x.decode(codec, 'replace'))
|
||||
|
||||
@ -83,6 +84,13 @@ class EXTHHeader(object): # {{{
|
||||
self.mi.language = lang
|
||||
except:
|
||||
pass
|
||||
elif idx == 525:
|
||||
try:
|
||||
pwm = content.decode(codec)
|
||||
if pwm:
|
||||
self.primary_writing_mode = pwm
|
||||
except Exception:
|
||||
pass
|
||||
elif idx == 527:
|
||||
try:
|
||||
ppd = content.decode(codec)
|
||||
@ -336,4 +344,3 @@ class MetadataHeader(BookHeader):
|
||||
except OverflowError:
|
||||
self.stream.seek(start)
|
||||
return self.stream.read()
|
||||
|
||||
|
@ -512,6 +512,9 @@ class Mobi8Reader(object):
|
||||
ppd = getattr(self.header.exth, 'page_progression_direction', None)
|
||||
if ppd in {'ltr', 'rtl', 'default'}:
|
||||
opf.page_progression_direction = ppd
|
||||
pwm = getattr(self.header.exth, 'primary_writing_mode', None)
|
||||
if pwm is not None:
|
||||
opf.primary_writing_mode = pwm
|
||||
|
||||
with open('metadata.opf', 'wb') as of, open('toc.ncx', 'wb') as ncx:
|
||||
opf.render(of, ncx, 'toc.ncx')
|
||||
|
@ -40,6 +40,7 @@ EXTH_CODES = {
|
||||
'lastupdatetime': 502,
|
||||
'title': 503,
|
||||
'language': 524,
|
||||
'primary_writing_mode': 525,
|
||||
'page_progression_direction': 527,
|
||||
}
|
||||
|
||||
@ -50,7 +51,7 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
|
||||
share_not_sync=True, cover_offset=None, thumbnail_offset=None,
|
||||
start_offset=None, mobi_doctype=2, num_of_resources=None,
|
||||
kf8_unknown_count=0, be_kindlegen2=False, kf8_header_index=None,
|
||||
page_progression_direction=None):
|
||||
page_progression_direction=None, primary_writing_mode=None):
|
||||
exth = BytesIO()
|
||||
nrecs = 0
|
||||
|
||||
@ -208,6 +209,12 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
|
||||
kf8_unknown_count))
|
||||
nrecs += 1
|
||||
|
||||
if primary_writing_mode:
|
||||
pwm = primary_writing_mode.encode('utf-8')
|
||||
exth.write(pack(b'>II', EXTH_CODES['primary_writing_mode'], len(pwm) + 8))
|
||||
exth.write(pwm)
|
||||
nrecs += 1
|
||||
|
||||
if page_progression_direction in {'rtl', 'ltr', 'default'}:
|
||||
ppd = bytes(page_progression_direction)
|
||||
exth.write(pack(b'>II', EXTH_CODES['page_progression_direction'], len(ppd) + 8))
|
||||
@ -219,5 +226,3 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
|
||||
pad = b'\0' * (4 - trail) # Always pad w/ at least 1 byte
|
||||
exth = [b'EXTH', pack(b'>II', len(exth) + 12, nrecs), exth, pad]
|
||||
return b''.join(exth)
|
||||
|
||||
|
||||
|
@ -209,6 +209,7 @@ class MOBIHeader(Header): # {{{
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
HEADER_FIELDS = {'compression', 'text_length', 'last_text_record', 'book_type',
|
||||
'first_non_text_record', 'title_length', 'language_code',
|
||||
'first_resource_record', 'exth_flags', 'fdst_record',
|
||||
@ -223,6 +224,7 @@ class KF8Book(object):
|
||||
self.build_records(writer, for_joint)
|
||||
self.used_images = writer.used_images
|
||||
self.page_progression_direction = writer.oeb.spine.page_progression_direction
|
||||
self.primary_writing_mode = writer.oeb.metadata.primary_writing_mode
|
||||
|
||||
def build_records(self, writer, for_joint):
|
||||
metadata = writer.oeb.metadata
|
||||
@ -311,7 +313,8 @@ class KF8Book(object):
|
||||
num_of_resources=self.num_of_resources,
|
||||
kf8_unknown_count=self.kuc, be_kindlegen2=True,
|
||||
start_offset=self.start_offset, mobi_doctype=self.book_type,
|
||||
page_progression_direction=self.page_progression_direction
|
||||
page_progression_direction=self.page_progression_direction,
|
||||
primary_writing_mode=self.primary_writing_mode
|
||||
)
|
||||
|
||||
kwargs = {field:getattr(self, field) for field in HEADER_FIELDS}
|
||||
@ -342,4 +345,3 @@ class KF8Book(object):
|
||||
|
||||
for rec in records:
|
||||
f.write(rec)
|
||||
|
||||
|
@ -782,6 +782,7 @@ class Metadata(object):
|
||||
def __init__(self, oeb):
|
||||
self.oeb = oeb
|
||||
self.items = defaultdict(list)
|
||||
self.primary_writing_mode = None
|
||||
|
||||
def add(self, term, value, attrib={}, nsmap={}, **kwargs):
|
||||
"""Add a new metadata item."""
|
||||
@ -864,6 +865,8 @@ class Metadata(object):
|
||||
for term in self.items:
|
||||
for item in self.items[term]:
|
||||
item.to_opf2(elem, nsrmap=nsrmap)
|
||||
if self.primary_writing_mode:
|
||||
elem.append(elem.makeelement(OPF('meta'), attrib={'name':'primary-writing-mode', 'content':self.primary_writing_mode}))
|
||||
return elem
|
||||
|
||||
|
||||
|
@ -137,7 +137,11 @@ class OEBReader(object):
|
||||
from calibre.ebooks.metadata.opf2 import OPF
|
||||
from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata
|
||||
stream = cStringIO.StringIO(etree.tostring(opf, xml_declaration=True, encoding='utf-8'))
|
||||
mi = OPF(stream).to_book_metadata()
|
||||
o = OPF(stream)
|
||||
pwm = o.primary_writing_mode
|
||||
if pwm:
|
||||
self.oeb.metadata.primary_writing_mode = pwm
|
||||
mi = o.to_book_metadata()
|
||||
if not mi.language:
|
||||
mi.language = get_lang().replace('_', '-')
|
||||
self.oeb.metadata.add('language', mi.language)
|
||||
|
Loading…
x
Reference in New Issue
Block a user