BabelDOC 0.2.23__tar.gz → 0.2.24__tar.gz
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-0.2.23 → babeldoc-0.2.24}/PKG-INFO +1 -1
- babeldoc-0.2.24/babeldoc/__init__.py +1 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/const.py +1 -1
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/backend/pdf_creater.py +233 -213
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/fontmap.py +5 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/main.py +1 -1
- {babeldoc-0.2.23 → babeldoc-0.2.24}/pyproject.toml +2 -2
- {babeldoc-0.2.23 → babeldoc-0.2.24}/uv.lock +1 -1
- babeldoc-0.2.23/babeldoc/__init__.py +0 -1
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.cursorignore +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/dependabot.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/labels.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/release-drafter.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/workflows/codeql.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/workflows/docs.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/workflows/labeler.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/workflows/publish-to-pypi.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.github/workflows/test.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.gitignore +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/.pre-commit-config.yaml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/LICENSE +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/README.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/assets/assets.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/assets/embedding_assets_metadata.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/asynchronize/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/converter.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/backend/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/frontend/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/frontend/il_creater.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/il_version_1.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/il_version_1.rnc +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/il_version_1.rng +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/il_version_1.xsd +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/add_debug_information.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/detect_scanned_file.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/il_translator.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/il_translator_llm_only.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/layout_parser.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/remove_descent.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/table_parser.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/midend/typesetting.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/translator/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/translator/cache.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/translator/translator.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/atomic_integer.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/layout_helper.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/priority_thread_pool_executor.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/style_helper.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/xml_converter.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/docvision/README.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/docvision/__init__.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/docvision/doclayout.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/docvision/rpc_doclayout.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/high_level.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/pdfinterp.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/progress_monitor.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/result_merger.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/split_manager.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/tools/generate_font_metadata.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/translation_config.py +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/CODE_OF_CONDUCT.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/CONTRIBUTING.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/CONTRIBUTOR_REWARD.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/README.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/README.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/deploy.sh +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-banner.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-contributor_reward_example.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-preview.gif +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-small-logo.png +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/index.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/intro-to-pdf-object.md +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/docs/requirements.txt +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/mkdocs.yml +0 -0
- {babeldoc-0.2.23 → babeldoc-0.2.24}/tests/test_translation_config.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.24"
|
|
@@ -158,27 +158,30 @@ class PDFCreater:
|
|
|
158
158
|
return self.get_xobj_available_fonts(page_xref_id, pdf)
|
|
159
159
|
|
|
160
160
|
def get_xobj_available_fonts(self, page_xref_id, pdf):
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
xref_id
|
|
170
|
-
|
|
161
|
+
try:
|
|
162
|
+
resources_type, r_id = pdf.xref_get_key(page_xref_id, "Resources")
|
|
163
|
+
if resources_type == "xref":
|
|
164
|
+
resource_xref_id = re.search("(\\d+) 0 R", r_id).group(1)
|
|
165
|
+
r_id = pdf.xref_object(int(resource_xref_id))
|
|
166
|
+
resources_type = "dict"
|
|
167
|
+
if resources_type == "dict":
|
|
168
|
+
xref_id = re.search("/Font (\\d+) 0 R", r_id)
|
|
169
|
+
if xref_id is not None:
|
|
170
|
+
xref_id = xref_id.group(1)
|
|
171
|
+
font_dict = pdf.xref_object(int(xref_id))
|
|
172
|
+
else:
|
|
173
|
+
search = re.search("/Font *<<(.+?)>>", r_id.replace("\n", " "))
|
|
174
|
+
if search is None:
|
|
175
|
+
# Have resources but no fonts
|
|
176
|
+
return set()
|
|
177
|
+
font_dict = search.group(1)
|
|
171
178
|
else:
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
r_id = int(r_id.split(" ")[0])
|
|
179
|
-
_, font_dict = pdf.xref_get_key(r_id, "Font")
|
|
180
|
-
fonts = re.findall("/([^ ]+?) ", font_dict)
|
|
181
|
-
return set(fonts)
|
|
179
|
+
r_id = int(r_id.split(" ")[0])
|
|
180
|
+
_, font_dict = pdf.xref_get_key(r_id, "Font")
|
|
181
|
+
fonts = re.findall("/([^ ]+?) ", font_dict)
|
|
182
|
+
return set(fonts)
|
|
183
|
+
except Exception:
|
|
184
|
+
return set()
|
|
182
185
|
|
|
183
186
|
def _debug_render_rectangle(
|
|
184
187
|
self,
|
|
@@ -633,213 +636,230 @@ class PDFCreater:
|
|
|
633
636
|
|
|
634
637
|
return False
|
|
635
638
|
|
|
636
|
-
def write(
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
xobj_available_fonts
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
639
|
+
def write(
|
|
640
|
+
self, translation_config: TranslationConfig, check_font_exists: bool = False
|
|
641
|
+
) -> TranslateResult:
|
|
642
|
+
try:
|
|
643
|
+
basename = Path(translation_config.input_file).stem
|
|
644
|
+
debug_suffix = ".debug" if translation_config.debug else ""
|
|
645
|
+
if (
|
|
646
|
+
translation_config.watermark_output_mode
|
|
647
|
+
!= WatermarkOutputMode.Watermarked
|
|
648
|
+
):
|
|
649
|
+
debug_suffix += ".no_watermark"
|
|
650
|
+
mono_out_path = translation_config.get_output_file_path(
|
|
651
|
+
f"{basename}{debug_suffix}.{translation_config.lang_out}.mono.pdf",
|
|
652
|
+
)
|
|
653
|
+
pdf = pymupdf.open(self.original_pdf_path)
|
|
654
|
+
self.font_mapper.add_font(pdf, self.docs)
|
|
655
|
+
with self.translation_config.progress_monitor.stage_start(
|
|
656
|
+
self.stage_name,
|
|
657
|
+
len(self.docs.page),
|
|
658
|
+
) as pbar:
|
|
659
|
+
for page in self.docs.page:
|
|
660
|
+
translation_config.raise_if_cancelled()
|
|
661
|
+
xobj_available_fonts = {}
|
|
662
|
+
xobj_draw_ops = {}
|
|
663
|
+
xobj_encoding_length_map = {}
|
|
664
|
+
available_font_list = self.get_available_font_list(pdf, page)
|
|
665
|
+
|
|
666
|
+
for xobj in page.pdf_xobject:
|
|
667
|
+
xobj_available_fonts[xobj.xobj_id] = available_font_list.copy()
|
|
668
|
+
try:
|
|
669
|
+
xobj_available_fonts[xobj.xobj_id].update(
|
|
670
|
+
self.get_xobj_available_fonts(xobj.xref_id, pdf),
|
|
671
|
+
)
|
|
672
|
+
except Exception:
|
|
673
|
+
pass
|
|
674
|
+
xobj_encoding_length_map[xobj.xobj_id] = {
|
|
675
|
+
f.font_id: f.encoding_length for f in xobj.pdf_font
|
|
676
|
+
}
|
|
677
|
+
xobj_op = BitStream()
|
|
678
|
+
xobj_op.append(xobj.base_operations.value.encode())
|
|
679
|
+
xobj_draw_ops[xobj.xobj_id] = xobj_op
|
|
680
|
+
page_encoding_length_map = {
|
|
681
|
+
f.font_id: f.encoding_length for f in page.pdf_font
|
|
667
682
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
chars
|
|
688
|
-
|
|
689
|
-
for paragraph in page.pdf_paragraph:
|
|
690
|
-
chars.extend(self.render_paragraph_to_char(paragraph))
|
|
691
|
-
|
|
692
|
-
# 渲染所有字符
|
|
693
|
-
for char in chars:
|
|
694
|
-
if char.char_unicode == "\n":
|
|
695
|
-
continue
|
|
696
|
-
if char.pdf_character_id is None:
|
|
697
|
-
# dummy char
|
|
698
|
-
continue
|
|
699
|
-
char_size = char.pdf_style.font_size
|
|
700
|
-
font_id = char.pdf_style.font_id
|
|
701
|
-
if char.xobj_id in xobj_available_fonts:
|
|
702
|
-
if font_id not in xobj_available_fonts[char.xobj_id]:
|
|
683
|
+
page_op = BitStream()
|
|
684
|
+
# q {ops_base}Q 1 0 0 1 {x0} {y0} cm {ops_new}
|
|
685
|
+
# page_op.append(b"q ")
|
|
686
|
+
page_op.append(page.base_operations.value.encode())
|
|
687
|
+
page_op.append(b" \n")
|
|
688
|
+
# page_op.append(b" Q ")
|
|
689
|
+
# page_op.append(
|
|
690
|
+
# f"q Q 1 0 0 1 {page.cropbox.box.x} {page.cropbox.box.y} cm \n".encode(),
|
|
691
|
+
# )
|
|
692
|
+
# 收集所有字符
|
|
693
|
+
chars = []
|
|
694
|
+
# 首先添加页面级别的字符
|
|
695
|
+
if page.pdf_character:
|
|
696
|
+
chars.extend(page.pdf_character)
|
|
697
|
+
# 然后添加段落中的字符
|
|
698
|
+
for paragraph in page.pdf_paragraph:
|
|
699
|
+
chars.extend(self.render_paragraph_to_char(paragraph))
|
|
700
|
+
|
|
701
|
+
# 渲染所有字符
|
|
702
|
+
for char in chars:
|
|
703
|
+
if char.char_unicode == "\n":
|
|
703
704
|
continue
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
else:
|
|
707
|
-
if font_id not in available_font_list:
|
|
705
|
+
if char.pdf_character_id is None:
|
|
706
|
+
# dummy char
|
|
708
707
|
continue
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
708
|
+
char_size = char.pdf_style.font_size
|
|
709
|
+
font_id = char.pdf_style.font_id
|
|
710
|
+
if char.xobj_id in xobj_available_fonts:
|
|
711
|
+
if (
|
|
712
|
+
check_font_exists
|
|
713
|
+
and font_id not in xobj_available_fonts[char.xobj_id]
|
|
714
|
+
):
|
|
715
|
+
continue
|
|
716
|
+
draw_op = xobj_draw_ops[char.xobj_id]
|
|
717
|
+
encoding_length_map = xobj_encoding_length_map[char.xobj_id]
|
|
718
|
+
else:
|
|
719
|
+
if check_font_exists and font_id not in available_font_list:
|
|
720
|
+
continue
|
|
721
|
+
draw_op = page_op
|
|
722
|
+
encoding_length_map = page_encoding_length_map
|
|
723
|
+
|
|
724
|
+
draw_op.append(b"q ")
|
|
725
|
+
self.render_graphic_state(draw_op, char.pdf_style.graphic_state)
|
|
726
|
+
if char.vertical:
|
|
727
|
+
draw_op.append(
|
|
728
|
+
f"BT /{font_id} {char_size:f} Tf 0 1 -1 0 {char.box.x2:f} {char.box.y:f} Tm ".encode(),
|
|
729
|
+
)
|
|
730
|
+
else:
|
|
731
|
+
draw_op.append(
|
|
732
|
+
f"BT /{font_id} {char_size:f} Tf 1 0 0 1 {char.box.x:f} {char.box.y:f} Tm ".encode(),
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
encoding_length = encoding_length_map[font_id]
|
|
736
|
+
# pdf32000-2008 page14:
|
|
737
|
+
# As hexadecimal data enclosed in angle brackets < >
|
|
738
|
+
# see 7.3.4.3, "Hexadecimal Strings."
|
|
715
739
|
draw_op.append(
|
|
716
|
-
f"
|
|
717
|
-
)
|
|
718
|
-
else:
|
|
719
|
-
draw_op.append(
|
|
720
|
-
f"BT /{font_id} {char_size:f} Tf 1 0 0 1 {char.box.x:f} {char.box.y:f} Tm ".encode(),
|
|
740
|
+
f"<{char.pdf_character_id:0{encoding_length * 2}x}>".upper().encode(),
|
|
721
741
|
)
|
|
722
742
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
743
|
+
draw_op.append(b" Tj ET Q \n")
|
|
744
|
+
for xobj in page.pdf_xobject:
|
|
745
|
+
draw_op = xobj_draw_ops[xobj.xobj_id]
|
|
746
|
+
try:
|
|
747
|
+
pdf.update_stream(xobj.xref_id, draw_op.tobytes())
|
|
748
|
+
except Exception:
|
|
749
|
+
logger.warning(
|
|
750
|
+
f"update xref {xobj.xref_id} stream fail, continue"
|
|
751
|
+
)
|
|
752
|
+
# pdf.update_stream(xobj.xref_id, b'')
|
|
753
|
+
for rect in page.pdf_rectangle:
|
|
754
|
+
self._debug_render_rectangle(page_op, rect)
|
|
755
|
+
draw_op = page_op
|
|
756
|
+
op_container = pdf.get_new_xref()
|
|
757
|
+
# Since this is a draw instruction container,
|
|
758
|
+
# no additional information is needed
|
|
759
|
+
pdf.update_object(op_container, "<<>>")
|
|
760
|
+
pdf.update_stream(op_container, draw_op.tobytes())
|
|
761
|
+
pdf[page.page_number].set_contents(op_container)
|
|
762
|
+
pbar.advance()
|
|
763
|
+
translation_config.raise_if_cancelled()
|
|
764
|
+
with self.translation_config.progress_monitor.stage_start(
|
|
765
|
+
SUBSET_FONT_STAGE_NAME,
|
|
766
|
+
1,
|
|
767
|
+
) as pbar:
|
|
768
|
+
if not translation_config.skip_clean:
|
|
769
|
+
pdf = self.subset_fonts_in_subprocess(
|
|
770
|
+
pdf, translation_config, tag="mono"
|
|
729
771
|
)
|
|
730
772
|
|
|
731
|
-
draw_op.append(b" Tj ET Q \n")
|
|
732
|
-
for xobj in page.pdf_xobject:
|
|
733
|
-
draw_op = xobj_draw_ops[xobj.xobj_id]
|
|
734
|
-
try:
|
|
735
|
-
pdf.update_stream(xobj.xref_id, draw_op.tobytes())
|
|
736
|
-
except Exception:
|
|
737
|
-
logger.warning(
|
|
738
|
-
f"update xref {xobj.xref_id} stream fail, continue"
|
|
739
|
-
)
|
|
740
|
-
# pdf.update_stream(xobj.xref_id, b'')
|
|
741
|
-
for rect in page.pdf_rectangle:
|
|
742
|
-
self._debug_render_rectangle(page_op, rect)
|
|
743
|
-
draw_op = page_op
|
|
744
|
-
op_container = pdf.get_new_xref()
|
|
745
|
-
# Since this is a draw instruction container,
|
|
746
|
-
# no additional information is needed
|
|
747
|
-
pdf.update_object(op_container, "<<>>")
|
|
748
|
-
pdf.update_stream(op_container, draw_op.tobytes())
|
|
749
|
-
pdf[page.page_number].set_contents(op_container)
|
|
750
773
|
pbar.advance()
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
SAVE_PDF_STAGE_NAME,
|
|
764
|
-
2,
|
|
765
|
-
) as pbar:
|
|
766
|
-
if not translation_config.no_mono:
|
|
767
|
-
if translation_config.debug:
|
|
774
|
+
with self.translation_config.progress_monitor.stage_start(
|
|
775
|
+
SAVE_PDF_STAGE_NAME,
|
|
776
|
+
2,
|
|
777
|
+
) as pbar:
|
|
778
|
+
if not translation_config.no_mono:
|
|
779
|
+
if translation_config.debug:
|
|
780
|
+
translation_config.raise_if_cancelled()
|
|
781
|
+
pdf.save(
|
|
782
|
+
f"{mono_out_path}.decompressed.pdf",
|
|
783
|
+
expand=True,
|
|
784
|
+
pretty=True,
|
|
785
|
+
)
|
|
768
786
|
translation_config.raise_if_cancelled()
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
pretty=True,
|
|
773
|
-
)
|
|
774
|
-
translation_config.raise_if_cancelled()
|
|
775
|
-
self.save_pdf_with_timeout(
|
|
776
|
-
pdf,
|
|
777
|
-
mono_out_path,
|
|
778
|
-
translation_config,
|
|
779
|
-
garbage=1,
|
|
780
|
-
deflate=True,
|
|
781
|
-
clean=not translation_config.skip_clean,
|
|
782
|
-
deflate_fonts=True,
|
|
783
|
-
linear=False,
|
|
784
|
-
tag="mono",
|
|
785
|
-
)
|
|
786
|
-
pbar.advance()
|
|
787
|
-
dual_out_path = None
|
|
788
|
-
if not translation_config.no_dual:
|
|
789
|
-
dual_out_path = translation_config.get_output_file_path(
|
|
790
|
-
f"{basename}{debug_suffix}.{translation_config.lang_out}.dual.pdf",
|
|
791
|
-
)
|
|
792
|
-
translation_config.raise_if_cancelled()
|
|
793
|
-
original_pdf = pymupdf.open(self.original_pdf_path)
|
|
794
|
-
translated_pdf = pdf
|
|
795
|
-
|
|
796
|
-
# Choose between alternating pages and side-by-side format
|
|
797
|
-
# Default to side-by-side if not specified
|
|
798
|
-
use_alternating_pages = translation_config.use_alternating_pages_dual
|
|
799
|
-
|
|
800
|
-
if use_alternating_pages:
|
|
801
|
-
# Create a dual PDF with alternating pages (original and translation)
|
|
802
|
-
dual = self.create_alternating_pages_dual_pdf(
|
|
803
|
-
self.original_pdf_path,
|
|
804
|
-
translated_pdf,
|
|
787
|
+
self.save_pdf_with_timeout(
|
|
788
|
+
pdf,
|
|
789
|
+
mono_out_path,
|
|
805
790
|
translation_config,
|
|
791
|
+
garbage=1,
|
|
792
|
+
deflate=True,
|
|
793
|
+
clean=not translation_config.skip_clean,
|
|
794
|
+
deflate_fonts=True,
|
|
795
|
+
linear=False,
|
|
796
|
+
tag="mono",
|
|
806
797
|
)
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
dual_out_path,
|
|
813
|
-
translation_config,
|
|
798
|
+
pbar.advance()
|
|
799
|
+
dual_out_path = None
|
|
800
|
+
if not translation_config.no_dual:
|
|
801
|
+
dual_out_path = translation_config.get_output_file_path(
|
|
802
|
+
f"{basename}{debug_suffix}.{translation_config.lang_out}.dual.pdf",
|
|
814
803
|
)
|
|
815
|
-
|
|
816
|
-
if translation_config.debug:
|
|
817
804
|
translation_config.raise_if_cancelled()
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
805
|
+
original_pdf = pymupdf.open(self.original_pdf_path)
|
|
806
|
+
translated_pdf = pdf
|
|
807
|
+
|
|
808
|
+
# Choose between alternating pages and side-by-side format
|
|
809
|
+
# Default to side-by-side if not specified
|
|
810
|
+
use_alternating_pages = (
|
|
811
|
+
translation_config.use_alternating_pages_dual
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
if use_alternating_pages:
|
|
815
|
+
# Create a dual PDF with alternating pages (original and translation)
|
|
816
|
+
dual = self.create_alternating_pages_dual_pdf(
|
|
817
|
+
self.original_pdf_path,
|
|
818
|
+
translated_pdf,
|
|
819
|
+
translation_config,
|
|
820
|
+
)
|
|
821
|
+
else:
|
|
822
|
+
# Create a dual PDF with side-by-side pages (original and translation)
|
|
823
|
+
dual = self.create_side_by_side_dual_pdf(
|
|
824
|
+
original_pdf,
|
|
825
|
+
translated_pdf,
|
|
826
|
+
dual_out_path,
|
|
827
|
+
translation_config,
|
|
824
828
|
)
|
|
825
829
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
830
|
+
if translation_config.debug:
|
|
831
|
+
translation_config.raise_if_cancelled()
|
|
832
|
+
try:
|
|
833
|
+
dual = self.write_debug_info(dual, translation_config)
|
|
834
|
+
except Exception:
|
|
835
|
+
logger.warning(
|
|
836
|
+
"Failed to write debug info to dual PDF",
|
|
837
|
+
exc_info=True,
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
self.save_pdf_with_timeout(
|
|
841
|
+
dual,
|
|
842
|
+
dual_out_path,
|
|
843
|
+
translation_config,
|
|
844
|
+
garbage=1,
|
|
845
|
+
deflate=True,
|
|
846
|
+
clean=not translation_config.skip_clean,
|
|
847
|
+
deflate_fonts=True,
|
|
848
|
+
linear=False,
|
|
849
|
+
tag="dual",
|
|
843
850
|
)
|
|
844
|
-
|
|
845
|
-
|
|
851
|
+
if translation_config.debug:
|
|
852
|
+
translation_config.raise_if_cancelled()
|
|
853
|
+
dual.save(
|
|
854
|
+
f"{dual_out_path}.decompressed.pdf",
|
|
855
|
+
expand=True,
|
|
856
|
+
pretty=True,
|
|
857
|
+
)
|
|
858
|
+
pbar.advance()
|
|
859
|
+
return TranslateResult(mono_out_path, dual_out_path)
|
|
860
|
+
except Exception:
|
|
861
|
+
logger.exception(
|
|
862
|
+
"Failed to create PDF: %s",
|
|
863
|
+
translation_config.input_file,
|
|
864
|
+
)
|
|
865
|
+
return self.write(translation_config, True)
|
|
@@ -187,6 +187,11 @@ class FontMapper:
|
|
|
187
187
|
pbar.advance(1)
|
|
188
188
|
for xref in range(1, xreflen):
|
|
189
189
|
pbar.advance(1)
|
|
190
|
+
# xref_type = doc_zh.xref_get_key(xref, "Type")
|
|
191
|
+
# if xref_type[1] == "/Page":
|
|
192
|
+
# resources_xref = doc_zh.xref_get_key(xref, "Resources")
|
|
193
|
+
# if resources_xref[0] == 'null':
|
|
194
|
+
# doc_zh.xref_set_key(xref, "Resources", f"<</Font<<>>>>")
|
|
190
195
|
for label in ["Resources/", ""]: # 可能是基于 xobj 的 res
|
|
191
196
|
try: # xref 读写可能出错
|
|
192
197
|
font_res = doc_zh.xref_get_key(xref, f"{label}Font")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "BabelDOC"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.24"
|
|
4
4
|
description = "Yet Another Document Translator"
|
|
5
5
|
license = "AGPL-3.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -148,7 +148,7 @@ pythonpath = [".", "src"]
|
|
|
148
148
|
testpaths = ["tests"]
|
|
149
149
|
|
|
150
150
|
[bumpver]
|
|
151
|
-
current_version = "0.2.
|
|
151
|
+
current_version = "0.2.24"
|
|
152
152
|
version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
|
|
153
153
|
|
|
154
154
|
[bumpver.file_patterns]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.23"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/babeldoc/document_il/utils/priority_thread_pool_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-with-transparent-background.png
RENAMED
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-big-logo-with-transparent-background.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-small-logo-with-transparent-background.png
RENAMED
|
File without changes
|
{babeldoc-0.2.23 → babeldoc-0.2.24}/docs/images/babeldoc-small-logo-with-transparent-background.svg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|