diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 348fa78107..aa63047edc 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -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: diff --git a/src/calibre/ebooks/mobi/reader/headers.py b/src/calibre/ebooks/mobi/reader/headers.py index cde6d2d4ed..433e80fbad 100644 --- a/src/calibre/ebooks/mobi/reader/headers.py +++ b/src/calibre/ebooks/mobi/reader/headers.py @@ -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() - diff --git a/src/calibre/ebooks/mobi/reader/mobi8.py b/src/calibre/ebooks/mobi/reader/mobi8.py index 14b72de538..ab47678f23 100644 --- a/src/calibre/ebooks/mobi/reader/mobi8.py +++ b/src/calibre/ebooks/mobi/reader/mobi8.py @@ -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') diff --git a/src/calibre/ebooks/mobi/writer8/exth.py b/src/calibre/ebooks/mobi/writer8/exth.py index 23f54cb2a2..6a068aec33 100644 --- a/src/calibre/ebooks/mobi/writer8/exth.py +++ b/src/calibre/ebooks/mobi/writer8/exth.py @@ -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) - - diff --git a/src/calibre/ebooks/mobi/writer8/mobi.py b/src/calibre/ebooks/mobi/writer8/mobi.py index ffa75f750d..1ce2e5105f 100644 --- a/src/calibre/ebooks/mobi/writer8/mobi.py +++ b/src/calibre/ebooks/mobi/writer8/mobi.py @@ -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) - diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 7c6cf2db80..453cee1e9f 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -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 diff --git a/src/calibre/ebooks/oeb/reader.py b/src/calibre/ebooks/oeb/reader.py index 5bc827ebde..789f82c94a 100644 --- a/src/calibre/ebooks/oeb/reader.py +++ b/src/calibre/ebooks/oeb/reader.py @@ -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)