Merge lp:~user-none/calibre/dev into lp:calibre

Proposed by John Schember
Status: Merged
Merged at revision: 7885
Proposed branch: lp:~user-none/calibre/dev
Merge into: lp:calibre
Diff against target: 125 lines (+28/-23)
1 file modified
src/calibre/ebooks/rtf/rtfml.py (+28/-23)
To merge this branch: bzr merge lp:~user-none/calibre/dev
Reviewer Review Type Date Requested Status
Kovid Goyal Pending
Review via email: mp+47922@code.launchpad.net

Description of the change

Output looks good in my testing. I'm using the heading styles from Word 2008 for OS X. The paragraph layout has been aggressively changed to accommodate turning h tags into RTF headings instead of styling the text to look like a heading. So calibre RTF output should have headings turned back into XHTML h tags via rtf2xml.

To post a comment you must log in.
lp:~user-none/calibre/dev updated
7885. By Kovid Goyal

RTF Output: Retain html headings as rtf headings when converting to rtf. Fixes #8641 (Chapters are lost when converting from Epub to RTF)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/calibre/ebooks/rtf/rtfml.py'
2--- src/calibre/ebooks/rtf/rtfml.py 2011-01-29 18:17:13 +0000
3+++ src/calibre/ebooks/rtf/rtfml.py 2011-01-30 04:08:59 +0000
4@@ -24,15 +24,15 @@
5 TAGS = {
6 'b': '\\b',
7 'del': '\\deleted',
8- 'h1': '\\b \\par \\pard \\hyphpar',
9- 'h2': '\\b \\par \\pard \\hyphpar',
10- 'h3': '\\b \\par \\pard \\hyphpar',
11- 'h4': '\\b \\par \\pard \\hyphpar',
12- 'h5': '\\b \\par \\pard \\hyphpar',
13- 'h6': '\\b \\par \\pard \\hyphpar',
14+ 'h1': '\\s1 \\afs32',
15+ 'h2': '\\s2 \\afs28',
16+ 'h3': '\\s3 \\afs28',
17+ 'h4': '\\s4 \\afs23',
18+ 'h5': '\\s5 \\afs23',
19+ 'h6': '\\s6 \\afs21',
20 'i': '\\i',
21- 'li': '\\par \\pard \\hyphpar \t',
22- 'p': '\\par \\pard \\hyphpar \t',
23+ 'li': '\t',
24+ 'p': '\t',
25 'sub': '\\sub',
26 'sup': '\\super',
27 'u': '\\ul',
28@@ -40,15 +40,9 @@
29
30 SINGLE_TAGS = {
31 'br': '\n{\\line }\n',
32- 'div': '\n{\\line }\n',
33-}
34-
35-SINGLE_TAGS_END = {
36- 'div': '\n{\\line }\n',
37 }
38
39 STYLES = [
40- ('display', {'block': '\\par \\pard \\hyphpar'}),
41 ('font-weight', {'bold': '\\b', 'bolder': '\\b'}),
42 ('font-style', {'italic': '\\i'}),
43 ('text-align', {'center': '\\qc', 'left': '\\ql', 'right': '\\qr'}),
44@@ -56,6 +50,7 @@
45 ]
46
47 BLOCK_TAGS = [
48+ 'div',
49 'p',
50 'h1',
51 'h2',
52@@ -113,7 +108,7 @@
53 stylizer = Stylizer(item.data, item.href, self.oeb_book,
54 self.opts, self.opts.output_profile)
55 output += self.dump_text(item.data.find(XHTML('body')), stylizer)
56- output += '{\\page } '
57+ output += '{\\page }'
58 for item in self.oeb_book.spine:
59 self.log.debug('Converting %s to RTF markup...' % item.href)
60 content = unicode(etree.tostring(item.data, encoding=unicode))
61@@ -122,6 +117,7 @@
62 content = etree.fromstring(content)
63 stylizer = Stylizer(content, item.href, self.oeb_book, self.opts, self.opts.output_profile)
64 output += self.dump_text(content.find(XHTML('body')), stylizer)
65+ output += '{\\page }'
66 output += self.footer()
67 output = self.insert_images(output)
68 output = self.clean_text(output)
69@@ -143,7 +139,16 @@
70 return text
71
72 def header(self):
73- return u'{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033' % (self.oeb_book.metadata.title[0].value, authors_to_string([x.value for x in self.oeb_book.metadata.creator]))
74+ header = u'{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' % (self.oeb_book.metadata.title[0].value, authors_to_string([x.value for x in self.oeb_book.metadata.creator]))
75+ return header + \
76+ '{\\fonttbl{\\f0\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f1\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f2\\fswiss\\fprq2\\fcharset128 Arial;}{\\f3\\fnil\\fprq2\\fcharset128 Arial;}{\\f4\\fnil\\fprq2\\fcharset128 MS Mincho;}{\\f5\\fnil\\fprq2\\fcharset128 Tahoma;}{\\f6\\fnil\\fprq0\\fcharset128 Tahoma;}}\n' \
77+ '{\\stylesheet{\\ql \\li0\\ri0\\nowidctlpar\\wrapdefault\\faauto\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\af25\\afs24\\alang1033 \\ltrch\\fcs0 \\fs24\\lang1033\\langfe255\\cgrid\\langnp1033\\langfenp255 \\snext0 Normal;}\n' \
78+ '{\\s1\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel0\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs32\\alang1033 \\ltrch\\fcs0 \\b\\fs32\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink21 heading 1;}\n' \
79+ '{\\s2\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel1\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\i\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink22 heading 2;}\n' \
80+ '{\\s3\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel2\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs28\\alang1033 \\ltrch\\fcs0 \\b\\fs28\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink23 heading 3;}\n' \
81+ '{\\s4\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel3\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\ai\\af0\\afs23\\alang1033 \\ltrch\\fcs0\\b\\i\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink24 heading 4;}\n' \
82+ '{\\s5\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel4\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs23\\alang1033 \\ltrch\\fcs0 \\b\\fs23\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink25 heading 5;}\n' \
83+ '{\\s6\\ql \\li0\\ri0\\sb240\\sa120\\keepn\\nowidctlpar\\wrapdefault\\faauto\\outlinelevel5\\rin0\\lin0\\itap0 \\rtlch\\fcs1 \\ab\\af0\\afs21\\alang1033 \\ltrch\\fcs0 \\b\\fs21\\lang1033\\langfe255\\loch\\f1\\hich\\af1\\dbch\\af26\\cgrid\\langnp1033\\langfenp255 \\sbasedon15 \\snext16 \\slink26 heading 6;}}\n'
84
85 def footer(self):
86 return ' }'
87@@ -184,6 +189,7 @@
88 # Remove excessive spaces
89 text = re.sub('[ ]{2,}', ' ', text)
90 text = re.sub('\t{2,}', '\t', text)
91+ text = re.sub('\t ', '\t', text)
92
93 # Remove excessive line breaks
94 text = re.sub(r'(\{\\line \}\s*){3,}', r'{\\line }{\\line }', text)
95@@ -226,7 +232,7 @@
96 block_start = ''
97 block_end = ''
98 if 'block' not in tag_stack:
99- block_start = '{\\par \\pard \\hyphpar '
100+ block_start = '{\\par\\pard\\hyphpar '
101 block_end = '}'
102 text += '%s SPECIAL_IMAGE-%s-REPLACE_ME %s' % (block_start, src, block_end)
103
104@@ -258,16 +264,15 @@
105 for i in range(0, tag_count):
106 end_tag = tag_stack.pop()
107 if end_tag != 'block':
108- text += u'}'
109-
110- single_tag_end = SINGLE_TAGS_END.get(tag, None)
111- if single_tag_end:
112- text += single_tag_end
113+ if tag in BLOCK_TAGS:
114+ text += u'\\par\\pard\\plain\\hyphpar}'
115+ else:
116+ text += u'}'
117
118 if hasattr(elem, 'tail') and elem.tail:
119 if 'block' in tag_stack:
120 text += '%s' % txt2rtf(elem.tail)
121 else:
122- text += '{\\par \\pard \\hyphpar %s}' % txt2rtf(elem.tail)
123+ text += '{\\par\\pard\\hyphpar %s}' % txt2rtf(elem.tail)
124
125 return text

Subscribers

People subscribed via source and target branches

to status/vote changes: