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.
Files changed (42) hide show
  1. babeldoc/__init__.py +1 -0
  2. babeldoc/asynchronize/__init__.py +51 -0
  3. babeldoc/const.py +7 -0
  4. babeldoc/converter.py +510 -0
  5. babeldoc/document_il/__init__.py +43 -0
  6. babeldoc/document_il/backend/__init__.py +0 -0
  7. babeldoc/document_il/backend/pdf_creater.py +402 -0
  8. babeldoc/document_il/frontend/__init__.py +0 -0
  9. babeldoc/document_il/frontend/il_creater.py +348 -0
  10. babeldoc/document_il/il_version_1.py +799 -0
  11. babeldoc/document_il/il_version_1.rnc +141 -0
  12. babeldoc/document_il/il_version_1.rng +390 -0
  13. babeldoc/document_il/il_version_1.xsd +235 -0
  14. babeldoc/document_il/midend/__init__.py +0 -0
  15. babeldoc/document_il/midend/add_debug_information.py +138 -0
  16. babeldoc/document_il/midend/il_translator.py +553 -0
  17. babeldoc/document_il/midend/layout_parser.py +180 -0
  18. babeldoc/document_il/midend/paragraph_finder.py +452 -0
  19. babeldoc/document_il/midend/remove_descent.py +168 -0
  20. babeldoc/document_il/midend/styles_and_formulas.py +701 -0
  21. babeldoc/document_il/midend/typesetting.py +761 -0
  22. babeldoc/document_il/translator/__init__.py +0 -0
  23. babeldoc/document_il/translator/cache.py +145 -0
  24. babeldoc/document_il/translator/translator.py +267 -0
  25. babeldoc/document_il/utils/fontmap.py +227 -0
  26. babeldoc/document_il/utils/layout_helper.py +467 -0
  27. babeldoc/document_il/utils/style_helper.py +86 -0
  28. babeldoc/document_il/xml_converter.py +51 -0
  29. babeldoc/docvision/README.md +0 -0
  30. babeldoc/docvision/__init__.py +0 -0
  31. babeldoc/docvision/doclayout.py +278 -0
  32. babeldoc/docvision/rpc_doclayout.py +162 -0
  33. babeldoc/high_level.py +468 -0
  34. babeldoc/main.py +466 -0
  35. babeldoc/pdfinterp.py +464 -0
  36. babeldoc/progress_monitor.py +146 -0
  37. babeldoc/translation_config.py +156 -0
  38. babeldoc-0.1.6.dist-info/METADATA +283 -0
  39. babeldoc-0.1.6.dist-info/RECORD +42 -0
  40. babeldoc-0.1.6.dist-info/WHEEL +4 -0
  41. babeldoc-0.1.6.dist-info/entry_points.txt +2 -0
  42. babeldoc-0.1.6.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,168 @@
1
+ import logging
2
+ from collections import Counter
3
+ from functools import cache
4
+
5
+ from babeldoc.document_il import il_version_1
6
+ from babeldoc.translation_config import TranslationConfig
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class RemoveDescent:
12
+ stage_name = "移除字体下沉"
13
+
14
+ def __init__(self, translation_config: TranslationConfig):
15
+ self.translation_config = translation_config
16
+
17
+ def _remove_char_descent(
18
+ self,
19
+ char: il_version_1.PdfCharacter,
20
+ font: il_version_1.PdfFont,
21
+ ) -> float | None:
22
+ """Remove descent from a single character and return the descent value.
23
+
24
+ Args:
25
+ char: The character to process
26
+ font: The font used by this character
27
+
28
+ Returns:
29
+ The descent value if it was removed, None otherwise
30
+ """
31
+ if (
32
+ char.box
33
+ and char.box.y is not None
34
+ and char.box.y2 is not None
35
+ and font
36
+ and hasattr(font, "descent")
37
+ ):
38
+ descent = font.descent * char.pdf_style.font_size / 1000
39
+ if char.vertical:
40
+ # For vertical text, remove descent from x coordinates
41
+ char.box.x += descent
42
+ char.box.x2 += descent
43
+ else:
44
+ # For horizontal text, remove descent from y coordinates
45
+ char.box.y -= descent
46
+ char.box.y2 -= descent
47
+ return descent
48
+ return None
49
+
50
+ def process(self, document: il_version_1.Document):
51
+ """Process the document to remove descent adjustments from character boxes.
52
+
53
+ Args:
54
+ document: The document to process
55
+ """
56
+ with self.translation_config.progress_monitor.stage_start(
57
+ self.stage_name,
58
+ len(document.page),
59
+ ) as pbar:
60
+ for page in document.page:
61
+ self.translation_config.raise_if_cancelled()
62
+ self.process_page(page)
63
+ pbar.advance()
64
+
65
+ def process_page(self, page: il_version_1.Page):
66
+ """Process a single page to remove descent adjustments.
67
+
68
+ Args:
69
+ page: The page to process
70
+ """
71
+ # Build font map including xobjects
72
+ fonts: dict[
73
+ str | int,
74
+ il_version_1.PdfFont | dict[str, il_version_1.PdfFont],
75
+ ] = {f.font_id: f for f in page.pdf_font}
76
+ page_fonts = {f.font_id: f for f in page.pdf_font}
77
+
78
+ # Add xobject fonts
79
+ for xobj in page.pdf_xobject:
80
+ fonts[xobj.xobj_id] = page_fonts.copy()
81
+ for font in xobj.pdf_font:
82
+ fonts[xobj.xobj_id][font.font_id] = font
83
+
84
+ @cache
85
+ def get_font(
86
+ font_id: str,
87
+ xobj_id: int | None = None,
88
+ ) -> il_version_1.PdfFont | None:
89
+ if xobj_id is not None and xobj_id in fonts:
90
+ font_map = fonts[xobj_id]
91
+ if isinstance(font_map, dict) and font_id in font_map:
92
+ return font_map[font_id]
93
+ return (
94
+ fonts.get(font_id)
95
+ if isinstance(fonts.get(font_id), il_version_1.PdfFont)
96
+ else None
97
+ )
98
+
99
+ # Process all standalone characters in the page
100
+ for char in page.pdf_character:
101
+ if font := get_font(char.pdf_style.font_id, char.xobj_id):
102
+ self._remove_char_descent(char, font)
103
+
104
+ # Process all paragraphs
105
+ for paragraph in page.pdf_paragraph:
106
+ descent_values = []
107
+ vertical_chars = []
108
+
109
+ # Process all characters in paragraph compositions
110
+ for comp in paragraph.pdf_paragraph_composition:
111
+ # Handle direct characters
112
+ if comp.pdf_character:
113
+ font = get_font(
114
+ comp.pdf_character.pdf_style.font_id,
115
+ comp.pdf_character.xobj_id,
116
+ )
117
+ if font:
118
+ descent = self._remove_char_descent(comp.pdf_character, font)
119
+ if descent is not None:
120
+ descent_values.append(descent)
121
+ vertical_chars.append(comp.pdf_character.vertical)
122
+
123
+ # Handle characters in PdfLine
124
+ elif comp.pdf_line:
125
+ for char in comp.pdf_line.pdf_character:
126
+ if font := get_font(char.pdf_style.font_id, char.xobj_id):
127
+ descent = self._remove_char_descent(char, font)
128
+ if descent is not None:
129
+ descent_values.append(descent)
130
+ vertical_chars.append(char.vertical)
131
+
132
+ # Handle characters in PdfFormula
133
+ elif comp.pdf_formula:
134
+ for char in comp.pdf_formula.pdf_character:
135
+ if font := get_font(char.pdf_style.font_id, char.xobj_id):
136
+ descent = self._remove_char_descent(char, font)
137
+ if descent is not None:
138
+ descent_values.append(descent)
139
+ vertical_chars.append(char.vertical)
140
+
141
+ # Handle characters in PdfSameStyleCharacters
142
+ elif comp.pdf_same_style_characters:
143
+ for char in comp.pdf_same_style_characters.pdf_character:
144
+ if font := get_font(char.pdf_style.font_id, char.xobj_id):
145
+ descent = self._remove_char_descent(char, font)
146
+ if descent is not None:
147
+ descent_values.append(descent)
148
+ vertical_chars.append(char.vertical)
149
+
150
+ # Adjust paragraph box based on most common descent value
151
+ if descent_values and paragraph.box:
152
+ # Calculate mode of descent values
153
+ descent_counter = Counter(descent_values)
154
+ most_common_descent = descent_counter.most_common(1)[0][0]
155
+
156
+ # Check if paragraph is vertical (all characters are vertical)
157
+ is_vertical = all(vertical_chars) if vertical_chars else False
158
+
159
+ # Adjust paragraph box
160
+ if paragraph.box.y is not None and paragraph.box.y2 is not None:
161
+ if is_vertical:
162
+ # For vertical paragraphs, adjust x coordinates
163
+ paragraph.box.x += most_common_descent
164
+ paragraph.box.x2 += most_common_descent
165
+ else:
166
+ # For horizontal paragraphs, adjust y coordinates
167
+ paragraph.box.y -= most_common_descent
168
+ paragraph.box.y2 -= most_common_descent