@@ -7,40 +7,47 @@ from subprocess import call
7
7
import requests
8
8
import git
9
9
import regex
10
+ import unicodedata
10
11
import se
11
12
import se .formatting
12
13
import se .epub
13
14
from bs4 import BeautifulSoup , UnicodeDammit
14
15
15
- def calculate_titlepage_lines ( str , ratio ):
16
- canvas_width = se . TITLEPAGE_WIDTH - ( se . TITLEPAGE_HORIZONTAL_PADDING * 2 )
17
- output_words = []
16
+
17
+ def get_word_widths ( str , target_height ):
18
+ words = []
18
19
for word in reversed (str .split ()):
19
20
width = 0
20
21
21
22
for char in word :
22
- width += (se .LEAGUE_SPARTAN_80_WIDTHS [char ] / ratio ) + se .TITLEPAGE_KERNING + se .TITLEPAGE_AVERAGE_SPACING
23
+ # Convert accented characters to unaccented characters
24
+ char = regex .sub (r"\p{M}" , "" , unicodedata .normalize ("NFKD" , char ))
25
+ width += (se .LEAGUE_SPARTAN_100_WIDTHS [char ] * target_height / 100 ) + se .LEAGUE_SPARTAN_KERNING + se .LEAGUE_SPARTAN_AVERAGE_SPACING
23
26
24
- width = width - se .TITLEPAGE_KERNING - se .TITLEPAGE_AVERAGE_SPACING
27
+ width = width - se .LEAGUE_SPARTAN_KERNING - se .LEAGUE_SPARTAN_AVERAGE_SPACING
25
28
26
- output_words .append ({"word" : word , "width" : width })
29
+ words .append ({"word" : word , "width" : width })
27
30
31
+ return words
32
+
33
+ def calculate_titlepage_lines (str , target_height , canvas_width ):
34
+ words = get_word_widths (str , target_height )
28
35
lines = []
29
36
current_line = ""
30
37
current_width = 0
31
- canvas_width = se . TITLEPAGE_WIDTH - ( se . TITLEPAGE_HORIZONTAL_PADDING * 2 )
32
- for word in output_words :
38
+
39
+ for word in words :
33
40
if current_width == 0 :
34
- current_width = current_width + word ["width" ]
41
+ current_width = word ["width" ]
35
42
else :
36
- current_width = current_width + (se .LEAGUE_SPARTAN_80_WIDTHS [" " ] / ratio ) + word ["width" ]
43
+ current_width = current_width + (se .LEAGUE_SPARTAN_100_WIDTHS [" " ] * target_height / 100 ) + word ["width" ]
37
44
38
45
if current_width < canvas_width :
39
46
current_line = word ["word" ] + " " + current_line
40
47
else :
41
48
lines .append (current_line .strip ())
42
49
current_line = word ["word" ]
43
- current_width = 0
50
+ current_width = word [ "width" ]
44
51
45
52
lines .append (current_line .strip ())
46
53
@@ -60,6 +67,7 @@ def generate_titlepage_svg(title, authors, contributors, title_string, templates
60
67
"""
61
68
62
69
svg = ""
70
+ canvas_width = se .TITLEPAGE_WIDTH - (se .TITLEPAGE_HORIZONTAL_PADDING * 2 )
63
71
64
72
if not isinstance (authors , list ):
65
73
authors = [authors ]
@@ -68,27 +76,21 @@ def generate_titlepage_svg(title, authors, contributors, title_string, templates
68
76
with open (os .path .join (templates_path , "titlepage.svg" ), "r" , encoding = "utf-8" ) as file :
69
77
svg = file .read ()
70
78
71
- # Store the template <text> elements for later use
72
- title_line_html = regex .search (r"<text.+?>TITLE LINE" , svg )[0 ].replace ("TITLE LINE" , "" )
73
- author_line_html = regex .search (r"<text.+?>AUTHOR LINE" , svg )[0 ].replace ("AUTHOR LINE" , "" )
74
- contributor_descriptor_html = regex .search (r"<text.+?>CONTRIBUTOR DESCRIPTOR" , svg )[0 ].replace ("CONTRIBUTOR DESCRIPTOR" , "" )
75
- contributor_line_html = regex .search (r"<text.+?>CONTRIBUTOR LINE" , svg )[0 ].replace ("CONTRIBUTOR LINE" , "" )
76
-
77
79
# Remove the template text elements from the SVG source, we'll write out to it later
78
80
svg = regex .sub (r"\s*<text.+</svg>" , "</svg>" , svg , flags = regex .DOTALL ).strip ()
79
81
80
82
# Calculate the title lines
81
- title_lines = calculate_titlepage_lines (title .upper (), 1 )
83
+ title_lines = calculate_titlepage_lines (title .upper (), se . TITLEPAGE_TITLE_HEIGHT , canvas_width )
82
84
83
85
# Calculate the author lines
84
86
authors_lines = []
85
87
for author in authors :
86
- authors_lines .append (calculate_titlepage_lines (author .upper (), se .TITLEPAGE_LEAGUE_SPARTAN_60_RATIO ))
88
+ authors_lines .append (calculate_titlepage_lines (author .upper (), se .TITLEPAGE_AUTHOR_HEIGHT , canvas_width ))
87
89
88
90
# Calculate the contributor lines
89
91
contributor_lines = []
90
92
for descriptor , contributor in contributors .items ():
91
- contributor_lines .append ([descriptor , calculate_titlepage_lines (contributor .upper (), se .TITLEPAGE_LEAGUE_SPARTAN_40_RATIO )])
93
+ contributor_lines .append ([descriptor , calculate_titlepage_lines (contributor .upper (), se .TITLEPAGE_CONTRIBUTOR_HEIGHT , canvas_width )])
92
94
93
95
# Construct the output
94
96
text_elements = ""
@@ -97,7 +99,7 @@ def generate_titlepage_svg(title, authors, contributors, title_string, templates
97
99
# Add the title
98
100
for line in title_lines :
99
101
y += se .TITLEPAGE_TITLE_HEIGHT
100
- text_elements += "\t " + title_line_html . replace ( "y =\" \" " , " y=\" {}\" " . format ( y )) + line + " </text>\n "
102
+ text_elements += "\t <text class =\" title \" x= \" 700 \" y=\" {:.0f }\" >{} </text>\n " . format ( y , line )
101
103
y += se .TITLEPAGE_TITLE_MARGIN
102
104
103
105
y -= se .TITLEPAGE_TITLE_MARGIN
@@ -108,7 +110,7 @@ def generate_titlepage_svg(title, authors, contributors, title_string, templates
108
110
for author_lines in authors_lines :
109
111
for line in author_lines :
110
112
y += se .TITLEPAGE_AUTHOR_HEIGHT
111
- text_elements += "\t " + author_line_html . replace ( "y =\" \" " , " y=\" {}\" " . format ( y )) + line + " </text>\n "
113
+ text_elements += "\t <text class =\" author \" x= \" 700 \" y=\" {:.0f }\" >{} </text>\n " . format ( y , line )
112
114
y += se .TITLEPAGE_AUTHOR_MARGIN
113
115
114
116
y -= se .TITLEPAGE_AUTHOR_MARGIN
@@ -118,26 +120,107 @@ def generate_titlepage_svg(title, authors, contributors, title_string, templates
118
120
y += se .TITLEPAGE_CONTRIBUTORS_SPACING
119
121
for contributor in contributor_lines :
120
122
y += se .TITLEPAGE_CONTRIBUTOR_DESCRIPTOR_HEIGHT
121
- text_elements += "\t " + contributor_descriptor_html . replace ( "y =\" \" " , " y=\" {}\" " .format (y )) + contributor [0 ] + "</text> \n "
123
+ text_elements += "\t <text class =\" contributor-descriptor \" x= \" 700 \" y=\" {:.0f }\" >{}</text> \n " .format (y , contributor [0 ])
122
124
y += se .TITLEPAGE_CONTRIBUTOR_MARGIN
123
125
124
126
for person in contributor [1 ]:
125
127
y += se .TITLEPAGE_CONTRIBUTOR_HEIGHT
126
- text_elements += "\t " + contributor_line_html . replace ( "y =\" \" " , " y=\" {}\" " . format ( y )) + person + " </text>\n "
128
+ text_elements += "\t <text class =\" contributor \" x= \" 700 \" y=\" {:.0f }\" >{} </text>\n " . format ( y , person )
127
129
y += se .TITLEPAGE_CONTRIBUTOR_MARGIN
128
130
129
131
y -= se .TITLEPAGE_CONTRIBUTOR_MARGIN
130
132
131
133
y += se .TITLEPAGE_CONTRIBUTOR_DESCRIPTOR_MARGIN
132
134
133
- y -= se .TITLEPAGE_CONTRIBUTOR_DESCRIPTOR_MARGIN + se .TITLEPAGE_CONTRIBUTOR_MARGIN
135
+ y -= se .TITLEPAGE_CONTRIBUTOR_DESCRIPTOR_MARGIN
136
+ else :
137
+ # Remove unused CSS
138
+ svg = regex .sub (r"\n\t\t\.contributor-descriptor{.+?}\n" , "" , svg , flags = regex .DOTALL )
139
+ svg = regex .sub (r"\n\t\t\.contributor{.+?}\n" , "" , svg , flags = regex .DOTALL )
134
140
135
141
y += se .TITLEPAGE_VERTICAL_PADDING
136
142
137
- svg = svg .replace ("</title>" , "</title>\n " + text_elements ).replace ("HEIGHT\" " , "{}\" " .format (y )).replace ("TITLESTRING" , title_string )
143
+ svg = svg .replace ("</svg>" , "\n " + text_elements + "</svg>" ).replace ("TITLESTRING" , title_string )
144
+ svg = regex .sub (r"viewBox=\".+?\"" , "viewBox=\" 0 0 1400 {:.0f}\" " .format (y ), svg )
138
145
139
146
return svg
140
147
148
+ def generate_cover_svg (title , authors , title_string , templates_path ):
149
+ svg = ""
150
+ canvas_width = se .COVER_TITLE_BOX_WIDTH - (se .COVER_TITLE_BOX_PADDING * 2 )
151
+
152
+ if not isinstance (authors , list ):
153
+ authors = [authors ]
154
+
155
+ # Read our template SVG to get some values before we begin
156
+ with open (os .path .join (templates_path , "cover.svg" ), "r" , encoding = "utf-8" ) as file :
157
+ svg = file .read ()
158
+
159
+ # Remove the template text elements from the SVG source, we'll write out to it later
160
+ svg = regex .sub (r"\s*<text.+</svg>" , "</svg>" , svg , flags = regex .DOTALL ).strip ()
161
+
162
+ # Calculate the title lines
163
+ title_height = se .COVER_TITLE_HEIGHT
164
+ title_class = "title"
165
+ title_lines = calculate_titlepage_lines (title .upper (), title_height , canvas_width )
166
+
167
+ if len (title_lines ) > 2 :
168
+ title_height = se .COVER_TITLE_SMALL_HEIGHT
169
+ title_class = "title-small"
170
+ title_lines = calculate_titlepage_lines (title .upper (), title_height , canvas_width )
171
+
172
+ if len (title_lines ) > 2 :
173
+ title_height = se .COVER_TITLE_XSMALL_HEIGHT
174
+ title_class = "title-xsmall"
175
+ title_lines = calculate_titlepage_lines (title .upper (), title_height , canvas_width )
176
+
177
+ # Calculate the author lines
178
+ authors_lines = []
179
+ for author in authors :
180
+ authors_lines .append (calculate_titlepage_lines (author .upper (), se .COVER_AUTHOR_HEIGHT , canvas_width ))
181
+
182
+ # Construct the output
183
+ text_elements = ""
184
+ y = se .COVER_TITLE_BOX_Y + \
185
+ + ((se .COVER_TITLE_BOX_HEIGHT \
186
+ - ( (len (title_lines ) * title_height ) \
187
+ + ( (len (title_lines ) - 1 ) * se .COVER_TITLE_MARGIN ) \
188
+ + se .COVER_AUTHOR_SPACING \
189
+ + (len (authors_lines ) * se .COVER_AUTHOR_HEIGHT ) \
190
+ )) / 2 )
191
+
192
+ # Add the title
193
+ for line in title_lines :
194
+ y += title_height
195
+ text_elements += "\t <text class=\" {}\" x=\" 700\" y=\" {:.0f}\" >{}</text>\n " .format (title_class , y , line )
196
+ y += se .COVER_TITLE_MARGIN
197
+
198
+ y -= se .COVER_TITLE_MARGIN
199
+
200
+ # Add the author(s)
201
+ y += se .COVER_AUTHOR_SPACING
202
+
203
+ for author_lines in authors_lines :
204
+ for line in author_lines :
205
+ y += se .COVER_AUTHOR_HEIGHT
206
+ text_elements += "\t <text class=\" author\" x=\" 700\" y=\" {:.0f}\" >{}</text>\n " .format (y , line )
207
+ y += se .COVER_AUTHOR_MARGIN
208
+
209
+ y -= se .COVER_AUTHOR_MARGIN
210
+
211
+ # Remove unused CSS
212
+ if title_class != "title" :
213
+ svg = regex .sub (r"\n\n\t\t\.title\{.+?\}" , "" , svg , flags = regex .DOTALL )
214
+
215
+ if title_class != "title-small" :
216
+ svg = regex .sub (r"\n\n\t\t\.title-small\{.+?\}" , "" , svg , flags = regex .DOTALL )
217
+
218
+ if title_class != "title-xsmall" :
219
+ svg = regex .sub (r"\n\n\t\t\.title-xsmall\{.+?\}" , "" , svg , flags = regex .DOTALL )
220
+
221
+ svg = svg .replace ("</svg>" , "\n " + text_elements + "</svg>" ).replace ("TITLESTRING" , title_string )
222
+
223
+ return svg
141
224
142
225
def get_wikipedia_url (string , get_nacoaf_url = False ):
143
226
# We try to get the Wikipedia URL by the subject by taking advantage of the fact that Wikipedia's special search will redirect you immediately
@@ -318,13 +401,7 @@ def main():
318
401
shutil .copy (os .path .normpath (templates_path + "/titlepage.xhtml" ), os .path .normpath (repo_name + "/src/epub/text/" ))
319
402
shutil .copy (os .path .normpath (templates_path + "/uncopyright.xhtml" ), os .path .normpath (repo_name + "/src/epub/text/" ))
320
403
shutil .copy (os .path .normpath (templates_path + "/titlepage.svg" ), os .path .normpath (repo_name + "/images/" ))
321
-
322
- if len (args .title ) < 15 :
323
- shutil .copy (os .path .normpath (templates_path + "/cover-short.svg" ), os .path .normpath (repo_name + "/images/cover.svg" ))
324
- elif len (args .title ) >= 30 :
325
- shutil .copy (os .path .normpath (templates_path + "/cover-long.svg" ), os .path .normpath (repo_name + "/images/cover.svg" ))
326
- else :
327
- shutil .copy (os .path .normpath (templates_path + "/cover.svg" ), os .path .normpath (repo_name + "/images/cover.svg" ))
404
+ shutil .copy (os .path .normpath (templates_path + "/cover.svg" ), os .path .normpath (repo_name + "/images/cover.svg" ))
328
405
329
406
# Try to find Wikipedia links if possible
330
407
author_wiki_url , author_nacoaf_url = get_wikipedia_url (args .author , True )
@@ -349,6 +426,11 @@ def main():
349
426
with open (os .path .join (repo_name , "images" , "titlepage.svg" ), "w" ) as file :
350
427
file .write (generate_titlepage_svg (args .title , args .author , contributors , title_string , templates_path ))
351
428
429
+ # Create the cover SVG
430
+ with open (os .path .join (repo_name , "images" , "cover.svg" ), "w" ) as file :
431
+ authors = ["Rudolph Eric Raspe" , "Willam Cervantes" ]
432
+ file .write (generate_cover_svg (args .title , authors , title_string , templates_path ))
433
+
352
434
if args .pg_url :
353
435
se .replace_in_file (os .path .normpath (repo_name + "/src/epub/text/imprint.xhtml" ), "PGLINK" , args .pg_url )
354
436
@@ -390,7 +472,6 @@ def main():
390
472
file .write (colophon_xhtml )
391
473
file .truncate ()
392
474
393
-
394
475
with open (os .path .join (repo_name , "src" , "epub" , "content.opf" ), "r+" , encoding = "utf-8" ) as file :
395
476
metadata_xhtml = file .read ()
396
477
0 commit comments