BabelDOC 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- babeldoc/__init__.py +1 -0
- babeldoc/asynchronize/__init__.py +51 -0
- babeldoc/const.py +7 -0
- babeldoc/converter.py +510 -0
- babeldoc/document_il/__init__.py +43 -0
- babeldoc/document_il/backend/__init__.py +0 -0
- babeldoc/document_il/backend/pdf_creater.py +402 -0
- babeldoc/document_il/frontend/__init__.py +0 -0
- babeldoc/document_il/frontend/il_creater.py +348 -0
- babeldoc/document_il/il_version_1.py +799 -0
- babeldoc/document_il/il_version_1.rnc +141 -0
- babeldoc/document_il/il_version_1.rng +390 -0
- babeldoc/document_il/il_version_1.xsd +235 -0
- babeldoc/document_il/midend/__init__.py +0 -0
- babeldoc/document_il/midend/add_debug_information.py +138 -0
- babeldoc/document_il/midend/il_translator.py +553 -0
- babeldoc/document_il/midend/layout_parser.py +180 -0
- babeldoc/document_il/midend/paragraph_finder.py +452 -0
- babeldoc/document_il/midend/remove_descent.py +168 -0
- babeldoc/document_il/midend/styles_and_formulas.py +701 -0
- babeldoc/document_il/midend/typesetting.py +761 -0
- babeldoc/document_il/translator/__init__.py +0 -0
- babeldoc/document_il/translator/cache.py +145 -0
- babeldoc/document_il/translator/translator.py +267 -0
- babeldoc/document_il/utils/fontmap.py +227 -0
- babeldoc/document_il/utils/layout_helper.py +467 -0
- babeldoc/document_il/utils/style_helper.py +86 -0
- babeldoc/document_il/xml_converter.py +51 -0
- babeldoc/docvision/README.md +0 -0
- babeldoc/docvision/__init__.py +0 -0
- babeldoc/docvision/doclayout.py +278 -0
- babeldoc/docvision/rpc_doclayout.py +162 -0
- babeldoc/high_level.py +468 -0
- babeldoc/main.py +466 -0
- babeldoc/pdfinterp.py +464 -0
- babeldoc/progress_monitor.py +146 -0
- babeldoc/translation_config.py +156 -0
- babeldoc-0.1.6.dist-info/METADATA +283 -0
- babeldoc-0.1.6.dist-info/RECORD +42 -0
- babeldoc-0.1.6.dist-info/WHEEL +4 -0
- babeldoc-0.1.6.dist-info/entry_points.txt +2 -0
- babeldoc-0.1.6.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import re
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pymupdf
|
|
6
|
+
from bitstring import BitStream
|
|
7
|
+
|
|
8
|
+
from babeldoc.document_il import il_version_1
|
|
9
|
+
from babeldoc.document_il.utils.fontmap import FontMapper
|
|
10
|
+
from babeldoc.translation_config import TranslateResult
|
|
11
|
+
from babeldoc.translation_config import TranslationConfig
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PDFCreater:
|
|
17
|
+
stage_name = "创建PDF文件"
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
original_pdf_path: str,
|
|
22
|
+
document: il_version_1.Document,
|
|
23
|
+
translation_config: TranslationConfig,
|
|
24
|
+
):
|
|
25
|
+
self.original_pdf_path = original_pdf_path
|
|
26
|
+
self.docs = document
|
|
27
|
+
self.font_path = translation_config.font
|
|
28
|
+
self.font_mapper = FontMapper(translation_config)
|
|
29
|
+
self.translation_config = translation_config
|
|
30
|
+
|
|
31
|
+
def render_graphic_state(
|
|
32
|
+
self,
|
|
33
|
+
draw_op: BitStream,
|
|
34
|
+
graphic_state: il_version_1.GraphicState,
|
|
35
|
+
):
|
|
36
|
+
if graphic_state is None:
|
|
37
|
+
return
|
|
38
|
+
# if graphic_state.stroking_color_space_name:
|
|
39
|
+
# draw_op.append(
|
|
40
|
+
# f"/{graphic_state.stroking_color_space_name} CS \n".encode()
|
|
41
|
+
# )
|
|
42
|
+
# if graphic_state.non_stroking_color_space_name:
|
|
43
|
+
# draw_op.append(
|
|
44
|
+
# f"/{graphic_state.non_stroking_color_space_name}"
|
|
45
|
+
# f" cs \n".encode()
|
|
46
|
+
# )
|
|
47
|
+
# if graphic_state.ncolor is not None:
|
|
48
|
+
# if len(graphic_state.ncolor) == 1:
|
|
49
|
+
# draw_op.append(f"{graphic_state.ncolor[0]} g \n".encode())
|
|
50
|
+
# elif len(graphic_state.ncolor) == 3:
|
|
51
|
+
# draw_op.append(
|
|
52
|
+
# f"{' '.join((str(x) for x in graphic_state.ncolor))} sc \n".encode()
|
|
53
|
+
# )
|
|
54
|
+
# if graphic_state.scolor is not None:
|
|
55
|
+
# if len(graphic_state.scolor) == 1:
|
|
56
|
+
# draw_op.append(f"{graphic_state.scolor[0]} G \n".encode())
|
|
57
|
+
# elif len(graphic_state.scolor) == 3:
|
|
58
|
+
# draw_op.append(
|
|
59
|
+
# f"{' '.join((str(x) for x in graphic_state.scolor))} SC \n".encode()
|
|
60
|
+
# )
|
|
61
|
+
|
|
62
|
+
if graphic_state.passthrough_per_char_instruction:
|
|
63
|
+
draw_op.append(
|
|
64
|
+
f"{graphic_state.passthrough_per_char_instruction} \n".encode(),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def render_paragraph_to_char(
|
|
68
|
+
self,
|
|
69
|
+
paragraph: il_version_1.PdfParagraph,
|
|
70
|
+
) -> list[il_version_1.PdfCharacter]:
|
|
71
|
+
chars = []
|
|
72
|
+
for composition in paragraph.pdf_paragraph_composition:
|
|
73
|
+
if not isinstance(composition.pdf_character, il_version_1.PdfCharacter):
|
|
74
|
+
logger.error(
|
|
75
|
+
f"Unknown composition type. "
|
|
76
|
+
f"This type only appears in the IL "
|
|
77
|
+
f"after the translation is completed."
|
|
78
|
+
f"During pdf rendering, this type is not supported."
|
|
79
|
+
f"Composition: {composition}. "
|
|
80
|
+
f"Paragraph: {paragraph}. ",
|
|
81
|
+
)
|
|
82
|
+
continue
|
|
83
|
+
chars.append(composition.pdf_character)
|
|
84
|
+
if not chars and paragraph.unicode:
|
|
85
|
+
logger.error(
|
|
86
|
+
f"Unable to export paragraphs that have "
|
|
87
|
+
f"not yet been formatted: {paragraph}",
|
|
88
|
+
)
|
|
89
|
+
return chars
|
|
90
|
+
return chars
|
|
91
|
+
|
|
92
|
+
def get_available_font_list(self, pdf, page):
|
|
93
|
+
page_xref_id = pdf[page.page_number].xref
|
|
94
|
+
return self.get_xobj_available_fonts(page_xref_id, pdf)
|
|
95
|
+
|
|
96
|
+
def get_xobj_available_fonts(self, page_xref_id, pdf):
|
|
97
|
+
resources_type, r_id = pdf.xref_get_key(page_xref_id, "Resources")
|
|
98
|
+
if resources_type == "xref":
|
|
99
|
+
resource_xref_id = re.search("(\\d+) 0 R", r_id).group(1)
|
|
100
|
+
r_id = pdf.xref_object(int(resource_xref_id))
|
|
101
|
+
resources_type = "dict"
|
|
102
|
+
if resources_type == "dict":
|
|
103
|
+
xref_id = re.search("/Font (\\d+) 0 R", r_id)
|
|
104
|
+
if xref_id is not None:
|
|
105
|
+
xref_id = xref_id.group(1)
|
|
106
|
+
font_dict = pdf.xref_object(int(xref_id))
|
|
107
|
+
else:
|
|
108
|
+
search = re.search("/Font *<<(.+?)>>", r_id.replace("\n", " "))
|
|
109
|
+
if search is None:
|
|
110
|
+
# Have resources but no fonts
|
|
111
|
+
return set()
|
|
112
|
+
font_dict = search.group(1)
|
|
113
|
+
else:
|
|
114
|
+
r_id = int(r_id.split(" ")[0])
|
|
115
|
+
_, font_dict = pdf.xref_get_key(r_id, "Font")
|
|
116
|
+
fonts = re.findall("/([^ ]+?) ", font_dict)
|
|
117
|
+
return set(fonts)
|
|
118
|
+
|
|
119
|
+
def _debug_render_rectangle(
|
|
120
|
+
self,
|
|
121
|
+
draw_op: BitStream,
|
|
122
|
+
rectangle: il_version_1.PdfRectangle,
|
|
123
|
+
):
|
|
124
|
+
"""Draw a debug rectangle in PDF for visualization purposes.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
draw_op: BitStream to append PDF drawing operations
|
|
128
|
+
rectangle: Rectangle object containing position information
|
|
129
|
+
"""
|
|
130
|
+
x1 = rectangle.box.x
|
|
131
|
+
y1 = rectangle.box.y
|
|
132
|
+
x2 = rectangle.box.x2
|
|
133
|
+
y2 = rectangle.box.y2
|
|
134
|
+
# Save graphics state
|
|
135
|
+
draw_op.append(b"q ")
|
|
136
|
+
|
|
137
|
+
# Set green color for debug visibility
|
|
138
|
+
draw_op.append(
|
|
139
|
+
rectangle.graphic_state.passthrough_per_char_instruction.encode(),
|
|
140
|
+
) # Green stroke
|
|
141
|
+
draw_op.append(b" 1 w ") # Line width
|
|
142
|
+
|
|
143
|
+
# Draw four lines manually
|
|
144
|
+
# Bottom line
|
|
145
|
+
draw_op.append(f"{x1} {y1} m {x2} {y1} l S ".encode())
|
|
146
|
+
# Right line
|
|
147
|
+
draw_op.append(f"{x2} {y1} m {x2} {y2} l S ".encode())
|
|
148
|
+
# Top line
|
|
149
|
+
draw_op.append(f"{x2} {y2} m {x1} {y2} l S ".encode())
|
|
150
|
+
# Left line
|
|
151
|
+
draw_op.append(f"{x1} {y2} m {x1} {y1} l S ".encode())
|
|
152
|
+
|
|
153
|
+
# Restore graphics state
|
|
154
|
+
draw_op.append(b"Q\n")
|
|
155
|
+
|
|
156
|
+
def write_debug_info(
|
|
157
|
+
self,
|
|
158
|
+
pdf: pymupdf.Document,
|
|
159
|
+
translation_config: TranslationConfig,
|
|
160
|
+
):
|
|
161
|
+
self.font_mapper.add_font(pdf, self.docs)
|
|
162
|
+
|
|
163
|
+
for page in self.docs.page:
|
|
164
|
+
_, r_id = pdf.xref_get_key(pdf[page.page_number].xref, "Contents")
|
|
165
|
+
resource_xref_id = re.search("(\\d+) 0 R", r_id).group(1)
|
|
166
|
+
base_op = pdf.xref_stream(int(resource_xref_id))
|
|
167
|
+
translation_config.raise_if_cancelled()
|
|
168
|
+
xobj_available_fonts = {}
|
|
169
|
+
xobj_draw_ops = {}
|
|
170
|
+
xobj_encoding_length_map = {}
|
|
171
|
+
available_font_list = self.get_available_font_list(pdf, page)
|
|
172
|
+
|
|
173
|
+
page_encoding_length_map = {
|
|
174
|
+
f.font_id: f.encoding_length for f in page.pdf_font
|
|
175
|
+
}
|
|
176
|
+
page_op = BitStream()
|
|
177
|
+
# q {ops_base}Q 1 0 0 1 {x0} {y0} cm {ops_new}
|
|
178
|
+
page_op.append(b"q ")
|
|
179
|
+
page_op.append(base_op)
|
|
180
|
+
page_op.append(b" Q ")
|
|
181
|
+
page_op.append(
|
|
182
|
+
f"q Q 1 0 0 1 {page.cropbox.box.x} {page.cropbox.box.y} cm \n".encode(),
|
|
183
|
+
)
|
|
184
|
+
# 收集所有字符
|
|
185
|
+
chars = []
|
|
186
|
+
# 首先添加页面级别的字符
|
|
187
|
+
if page.pdf_character:
|
|
188
|
+
chars.extend(page.pdf_character)
|
|
189
|
+
# 然后添加段落中的字符
|
|
190
|
+
for paragraph in page.pdf_paragraph:
|
|
191
|
+
chars.extend(self.render_paragraph_to_char(paragraph))
|
|
192
|
+
|
|
193
|
+
# 渲染所有字符
|
|
194
|
+
for char in chars:
|
|
195
|
+
if not getattr(char, "debug_info", False):
|
|
196
|
+
continue
|
|
197
|
+
if char.char_unicode == "\n":
|
|
198
|
+
continue
|
|
199
|
+
if char.pdf_character_id is None:
|
|
200
|
+
# dummy char
|
|
201
|
+
continue
|
|
202
|
+
char_size = char.pdf_style.font_size
|
|
203
|
+
font_id = char.pdf_style.font_id
|
|
204
|
+
|
|
205
|
+
if font_id not in available_font_list:
|
|
206
|
+
continue
|
|
207
|
+
draw_op = page_op
|
|
208
|
+
encoding_length_map = page_encoding_length_map
|
|
209
|
+
|
|
210
|
+
draw_op.append(b"q ")
|
|
211
|
+
self.render_graphic_state(draw_op, char.pdf_style.graphic_state)
|
|
212
|
+
if char.vertical:
|
|
213
|
+
draw_op.append(
|
|
214
|
+
f"BT /{font_id} {char_size:f} Tf 0 1 -1 0 {char.box.x2:f} {char.box.y:f} Tm ".encode(),
|
|
215
|
+
)
|
|
216
|
+
else:
|
|
217
|
+
draw_op.append(
|
|
218
|
+
f"BT /{font_id} {char_size:f} Tf 1 0 0 1 {char.box.x:f} {char.box.y:f} Tm ".encode(),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
encoding_length = encoding_length_map[font_id]
|
|
222
|
+
# pdf32000-2008 page14:
|
|
223
|
+
# As hexadecimal data enclosed in angle brackets < >
|
|
224
|
+
# see 7.3.4.3, "Hexadecimal Strings."
|
|
225
|
+
draw_op.append(
|
|
226
|
+
f"<{char.pdf_character_id:0{encoding_length * 2}x}>".upper().encode(),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
draw_op.append(b" Tj ET Q \n")
|
|
230
|
+
for rect in page.pdf_rectangle:
|
|
231
|
+
if not rect.debug_info:
|
|
232
|
+
continue
|
|
233
|
+
self._debug_render_rectangle(page_op, rect)
|
|
234
|
+
draw_op = page_op
|
|
235
|
+
# Since this is a draw instruction container,
|
|
236
|
+
# no additional information is needed
|
|
237
|
+
pdf.update_stream(int(resource_xref_id), draw_op.tobytes())
|
|
238
|
+
translation_config.raise_if_cancelled()
|
|
239
|
+
pdf.subset_fonts(fallback=False)
|
|
240
|
+
|
|
241
|
+
def write(self, translation_config: TranslationConfig) -> TranslateResult:
|
|
242
|
+
basename = Path(translation_config.input_file).stem
|
|
243
|
+
debug_suffix = ".debug" if translation_config.debug else ""
|
|
244
|
+
mono_out_path = translation_config.get_output_file_path(
|
|
245
|
+
f"{basename}{debug_suffix}.{translation_config.lang_out}.mono.pdf",
|
|
246
|
+
)
|
|
247
|
+
pdf = pymupdf.open(self.original_pdf_path)
|
|
248
|
+
self.font_mapper.add_font(pdf, self.docs)
|
|
249
|
+
with self.translation_config.progress_monitor.stage_start(
|
|
250
|
+
self.stage_name,
|
|
251
|
+
len(self.docs.page) + 2,
|
|
252
|
+
) as pbar:
|
|
253
|
+
for page in self.docs.page:
|
|
254
|
+
translation_config.raise_if_cancelled()
|
|
255
|
+
xobj_available_fonts = {}
|
|
256
|
+
xobj_draw_ops = {}
|
|
257
|
+
xobj_encoding_length_map = {}
|
|
258
|
+
available_font_list = self.get_available_font_list(pdf, page)
|
|
259
|
+
|
|
260
|
+
for xobj in page.pdf_xobject:
|
|
261
|
+
xobj_available_fonts[xobj.xobj_id] = available_font_list.copy()
|
|
262
|
+
try:
|
|
263
|
+
xobj_available_fonts[xobj.xobj_id].update(
|
|
264
|
+
self.get_xobj_available_fonts(xobj.xref_id, pdf),
|
|
265
|
+
)
|
|
266
|
+
except Exception:
|
|
267
|
+
pass
|
|
268
|
+
xobj_encoding_length_map[xobj.xobj_id] = {
|
|
269
|
+
f.font_id: f.encoding_length for f in xobj.pdf_font
|
|
270
|
+
}
|
|
271
|
+
xobj_op = BitStream()
|
|
272
|
+
xobj_op.append(xobj.base_operations.value.encode())
|
|
273
|
+
xobj_draw_ops[xobj.xobj_id] = xobj_op
|
|
274
|
+
page_encoding_length_map = {
|
|
275
|
+
f.font_id: f.encoding_length for f in page.pdf_font
|
|
276
|
+
}
|
|
277
|
+
page_op = BitStream()
|
|
278
|
+
# q {ops_base}Q 1 0 0 1 {x0} {y0} cm {ops_new}
|
|
279
|
+
page_op.append(b"q ")
|
|
280
|
+
page_op.append(page.base_operations.value.encode())
|
|
281
|
+
page_op.append(b" Q ")
|
|
282
|
+
page_op.append(
|
|
283
|
+
f"q Q 1 0 0 1 {page.cropbox.box.x} {page.cropbox.box.y} cm \n".encode(),
|
|
284
|
+
)
|
|
285
|
+
# 收集所有字符
|
|
286
|
+
chars = []
|
|
287
|
+
# 首先添加页面级别的字符
|
|
288
|
+
if page.pdf_character:
|
|
289
|
+
chars.extend(page.pdf_character)
|
|
290
|
+
# 然后添加段落中的字符
|
|
291
|
+
for paragraph in page.pdf_paragraph:
|
|
292
|
+
chars.extend(self.render_paragraph_to_char(paragraph))
|
|
293
|
+
|
|
294
|
+
# 渲染所有字符
|
|
295
|
+
for char in chars:
|
|
296
|
+
if char.char_unicode == "\n":
|
|
297
|
+
continue
|
|
298
|
+
if char.pdf_character_id is None:
|
|
299
|
+
# dummy char
|
|
300
|
+
continue
|
|
301
|
+
char_size = char.pdf_style.font_size
|
|
302
|
+
font_id = char.pdf_style.font_id
|
|
303
|
+
if char.xobj_id in xobj_available_fonts:
|
|
304
|
+
if font_id not in xobj_available_fonts[char.xobj_id]:
|
|
305
|
+
continue
|
|
306
|
+
draw_op = xobj_draw_ops[char.xobj_id]
|
|
307
|
+
encoding_length_map = xobj_encoding_length_map[char.xobj_id]
|
|
308
|
+
else:
|
|
309
|
+
if font_id not in available_font_list:
|
|
310
|
+
continue
|
|
311
|
+
draw_op = page_op
|
|
312
|
+
encoding_length_map = page_encoding_length_map
|
|
313
|
+
|
|
314
|
+
draw_op.append(b"q ")
|
|
315
|
+
self.render_graphic_state(draw_op, char.pdf_style.graphic_state)
|
|
316
|
+
if char.vertical:
|
|
317
|
+
draw_op.append(
|
|
318
|
+
f"BT /{font_id} {char_size:f} Tf 0 1 -1 0 {char.box.x2:f} {char.box.y:f} Tm ".encode(),
|
|
319
|
+
)
|
|
320
|
+
else:
|
|
321
|
+
draw_op.append(
|
|
322
|
+
f"BT /{font_id} {char_size:f} Tf 1 0 0 1 {char.box.x:f} {char.box.y:f} Tm ".encode(),
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
encoding_length = encoding_length_map[font_id]
|
|
326
|
+
# pdf32000-2008 page14:
|
|
327
|
+
# As hexadecimal data enclosed in angle brackets < >
|
|
328
|
+
# see 7.3.4.3, "Hexadecimal Strings."
|
|
329
|
+
draw_op.append(
|
|
330
|
+
f"<{char.pdf_character_id:0{encoding_length * 2}x}>".upper().encode(),
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
draw_op.append(b" Tj ET Q \n")
|
|
334
|
+
for xobj in page.pdf_xobject:
|
|
335
|
+
draw_op = xobj_draw_ops[xobj.xobj_id]
|
|
336
|
+
pdf.update_stream(xobj.xref_id, draw_op.tobytes())
|
|
337
|
+
# pdf.update_stream(xobj.xref_id, b'')
|
|
338
|
+
for rect in page.pdf_rectangle:
|
|
339
|
+
self._debug_render_rectangle(page_op, rect)
|
|
340
|
+
draw_op = page_op
|
|
341
|
+
op_container = pdf.get_new_xref()
|
|
342
|
+
# Since this is a draw instruction container,
|
|
343
|
+
# no additional information is needed
|
|
344
|
+
pdf.update_object(op_container, "<<>>")
|
|
345
|
+
pdf.update_stream(op_container, draw_op.tobytes())
|
|
346
|
+
pdf[page.page_number].set_contents(op_container)
|
|
347
|
+
pbar.advance()
|
|
348
|
+
translation_config.raise_if_cancelled()
|
|
349
|
+
if not translation_config.skip_clean:
|
|
350
|
+
pdf.subset_fonts(fallback=False)
|
|
351
|
+
if not translation_config.no_mono:
|
|
352
|
+
if translation_config.debug:
|
|
353
|
+
translation_config.raise_if_cancelled()
|
|
354
|
+
pdf.save(
|
|
355
|
+
f"{mono_out_path}.decompressed.pdf",
|
|
356
|
+
expand=True,
|
|
357
|
+
pretty=True,
|
|
358
|
+
)
|
|
359
|
+
translation_config.raise_if_cancelled()
|
|
360
|
+
pdf.save(
|
|
361
|
+
mono_out_path,
|
|
362
|
+
garbage=3,
|
|
363
|
+
deflate=True,
|
|
364
|
+
clean=not translation_config.skip_clean,
|
|
365
|
+
deflate_fonts=True,
|
|
366
|
+
linear=True,
|
|
367
|
+
)
|
|
368
|
+
pbar.advance()
|
|
369
|
+
dual_out_path = None
|
|
370
|
+
if not translation_config.no_dual:
|
|
371
|
+
dual_out_path = translation_config.get_output_file_path(
|
|
372
|
+
f"{basename}{debug_suffix}.{translation_config.lang_out}.dual.pdf",
|
|
373
|
+
)
|
|
374
|
+
translation_config.raise_if_cancelled()
|
|
375
|
+
dual = pymupdf.open(self.original_pdf_path)
|
|
376
|
+
if translation_config.debug:
|
|
377
|
+
translation_config.raise_if_cancelled()
|
|
378
|
+
self.write_debug_info(dual, translation_config)
|
|
379
|
+
dual.insert_file(pdf)
|
|
380
|
+
page_count = pdf.page_count
|
|
381
|
+
for page_id in range(page_count):
|
|
382
|
+
if translation_config.dual_translate_first:
|
|
383
|
+
dual.move_page(page_count + page_id, page_id * 2)
|
|
384
|
+
else:
|
|
385
|
+
dual.move_page(page_count + page_id, page_id * 2 + 1)
|
|
386
|
+
dual.save(
|
|
387
|
+
dual_out_path,
|
|
388
|
+
garbage=3,
|
|
389
|
+
deflate=True,
|
|
390
|
+
clean=not translation_config.skip_clean,
|
|
391
|
+
deflate_fonts=True,
|
|
392
|
+
linear=True,
|
|
393
|
+
)
|
|
394
|
+
if translation_config.debug:
|
|
395
|
+
translation_config.raise_if_cancelled()
|
|
396
|
+
dual.save(
|
|
397
|
+
f"{dual_out_path}.decompressed.pdf",
|
|
398
|
+
expand=True,
|
|
399
|
+
pretty=True,
|
|
400
|
+
)
|
|
401
|
+
pbar.advance()
|
|
402
|
+
return TranslateResult(mono_out_path, dual_out_path)
|
|
File without changes
|