NotYAFC 1.0.0__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.
- font_converter/__init__.py +4 -0
- font_converter/__main__.py +45 -0
- font_converter/assets/ico.png +0 -0
- font_converter/assets/notyafc-1024.png +0 -0
- font_converter/assets/notyafc.ico +0 -0
- font_converter/assets/notyafc.svg +15 -0
- font_converter/cli.py +543 -0
- font_converter/constants.py +27 -0
- font_converter/contours.py +336 -0
- font_converter/css_kit.py +77 -0
- font_converter/finder.py +213 -0
- font_converter/font.py +530 -0
- font_converter/gui/__init__.py +1 -0
- font_converter/gui/conversion_dialog.py +110 -0
- font_converter/gui/file_list.py +411 -0
- font_converter/gui/instance_tree.py +583 -0
- font_converter/gui/logs.py +51 -0
- font_converter/gui/organization_dialog.py +417 -0
- font_converter/gui/profile_options.py +316 -0
- font_converter/gui/profiles.py +17 -0
- font_converter/gui/scanner.py +42 -0
- font_converter/gui/styles.py +658 -0
- font_converter/gui/widgets.py +495 -0
- font_converter/gui/window.py +1768 -0
- font_converter/inspection.py +169 -0
- font_converter/merge_curves.py +499 -0
- font_converter/otf_builder.py +144 -0
- font_converter/qu2cu.py +117 -0
- font_converter/service.py +729 -0
- font_converter/ttf_builder.py +107 -0
- notyafc-1.0.0.dist-info/METADATA +256 -0
- notyafc-1.0.0.dist-info/RECORD +34 -0
- notyafc-1.0.0.dist-info/WHEEL +4 -0
- notyafc-1.0.0.dist-info/entry_points.txt +6 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""Profile-specific controls and typed option construction for the converter."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import replace
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from PySide6.QtCore import Signal
|
|
7
|
+
from PySide6.QtWidgets import (
|
|
8
|
+
QCheckBox,
|
|
9
|
+
QGridLayout,
|
|
10
|
+
QGroupBox,
|
|
11
|
+
QHBoxLayout,
|
|
12
|
+
QLabel,
|
|
13
|
+
QSpinBox,
|
|
14
|
+
QVBoxLayout,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from font_converter.gui.widgets import (
|
|
18
|
+
UPM_STEP_VALUES,
|
|
19
|
+
DecimalSpinBox,
|
|
20
|
+
StepperField,
|
|
21
|
+
UpmSpinBox,
|
|
22
|
+
)
|
|
23
|
+
from font_converter.service import (
|
|
24
|
+
ConversionOptions,
|
|
25
|
+
ConversionSettings,
|
|
26
|
+
InstanceSpec,
|
|
27
|
+
OtfToTtfOptions,
|
|
28
|
+
SfntToWebOptions,
|
|
29
|
+
TtcToSfntOptions,
|
|
30
|
+
TtfToOtfOptions,
|
|
31
|
+
VarToStaticOptions,
|
|
32
|
+
WebFormat,
|
|
33
|
+
Woff2ToSfntOptions,
|
|
34
|
+
WoffToSfntOptions,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ProfileOptionsPanel(QGroupBox):
|
|
39
|
+
"""Own controls that change with a selected conversion profile."""
|
|
40
|
+
|
|
41
|
+
compatibilityChanged = Signal()
|
|
42
|
+
validityChanged = Signal()
|
|
43
|
+
|
|
44
|
+
def __init__(self) -> None:
|
|
45
|
+
super().__init__("Conversion options")
|
|
46
|
+
self.setObjectName("card")
|
|
47
|
+
self._outline_profile = False
|
|
48
|
+
self._variable_profile = False
|
|
49
|
+
self._web_profile = False
|
|
50
|
+
self._instance_outlines: set[str] = set()
|
|
51
|
+
options = QVBoxLayout(self)
|
|
52
|
+
options.setContentsMargins(16, 12, 16, 14)
|
|
53
|
+
options.setSpacing(9)
|
|
54
|
+
|
|
55
|
+
self.instances_hint = QLabel(
|
|
56
|
+
"Check the instances to export for each font. Select a font or an instance "
|
|
57
|
+
"and use “Add custom instance” to add one for that font."
|
|
58
|
+
)
|
|
59
|
+
self.instances_hint.setObjectName("stepHint")
|
|
60
|
+
self.instances_hint.setWordWrap(True)
|
|
61
|
+
|
|
62
|
+
self.tolerance_label = QLabel("Tolerance (0.0–3.0)")
|
|
63
|
+
self.tolerance = DecimalSpinBox()
|
|
64
|
+
self.tolerance.setRange(0, 3)
|
|
65
|
+
self.tolerance.setSingleStep(0.1)
|
|
66
|
+
self.tolerance.setValue(1.0)
|
|
67
|
+
self.tolerance.setDecimals(2)
|
|
68
|
+
self.tolerance_field = StepperField(self.tolerance, tab_buttons=True)
|
|
69
|
+
self.tolerance_field.setFixedWidth(170)
|
|
70
|
+
tolerance_tooltip = (
|
|
71
|
+
"Higher values allow larger curve deviations and usually produce fewer points; "
|
|
72
|
+
"lower values preserve more detail. "
|
|
73
|
+
"Tolerance is in thousandths of an em; actual deviation scales with UPM."
|
|
74
|
+
)
|
|
75
|
+
self.tolerance_label.setToolTip(tolerance_tooltip)
|
|
76
|
+
self.tolerance.setToolTip(tolerance_tooltip)
|
|
77
|
+
self.tolerance_field.setToolTip(tolerance_tooltip)
|
|
78
|
+
self.use_target_upm = QCheckBox("Set target UPM")
|
|
79
|
+
upm_tooltip = "UPM (units per em) is the font's design-grid size. Scale converted fonts to this value."
|
|
80
|
+
self.use_target_upm.setToolTip(upm_tooltip)
|
|
81
|
+
self.target_upm = UpmSpinBox()
|
|
82
|
+
self.target_upm_field = StepperField(self.target_upm, tab_buttons=True)
|
|
83
|
+
self.target_upm_field.setFixedWidth(170)
|
|
84
|
+
self.target_upm_field.setEnabled(False)
|
|
85
|
+
self.target_upm.setToolTip(upm_tooltip)
|
|
86
|
+
self.target_upm_field.setToolTip(upm_tooltip)
|
|
87
|
+
self.use_target_upm.toggled.connect(self.target_upm_field.setEnabled)
|
|
88
|
+
|
|
89
|
+
self.subroutinize = QCheckBox("Subroutinize")
|
|
90
|
+
self.subroutinize.setChecked(True)
|
|
91
|
+
self.subroutinize.setToolTip(
|
|
92
|
+
"Compress CFF outlines using shared subroutines (PostScript outlines only)."
|
|
93
|
+
)
|
|
94
|
+
self.optimize_contours_label = QLabel("Simplify contours (0–3)")
|
|
95
|
+
self.optimize_contours_label.setWordWrap(True)
|
|
96
|
+
self.optimize_contours = QSpinBox()
|
|
97
|
+
self.optimize_contours.setRange(0, 3)
|
|
98
|
+
self.optimize_contours.setSpecialValueText("Off")
|
|
99
|
+
self.optimize_contours.setToolTip(
|
|
100
|
+
"Merge adjacent smooth curve segments to reduce the number of points (experimental). "
|
|
101
|
+
"Higher values allow larger deviations; 0 disables simplification."
|
|
102
|
+
)
|
|
103
|
+
self.optimize_contours_field = StepperField(self.optimize_contours, tab_buttons=True)
|
|
104
|
+
self.optimize_contours_field.setFixedWidth(170)
|
|
105
|
+
self.optimize_contours_label.setToolTip(self.optimize_contours.toolTip())
|
|
106
|
+
self.optimize_contours_field.setToolTip(self.optimize_contours.toolTip())
|
|
107
|
+
self.autohint = QCheckBox("Autohint")
|
|
108
|
+
self.autohint.setChecked(True)
|
|
109
|
+
self.autohint.setToolTip(
|
|
110
|
+
"Add TrueType hinting instructions with ttfautohint (TrueType outlines only)."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
spin_grid = QGridLayout()
|
|
114
|
+
spin_grid.setHorizontalSpacing(12)
|
|
115
|
+
spin_grid.setVerticalSpacing(12)
|
|
116
|
+
spin_grid.addWidget(self.tolerance_label, 0, 0)
|
|
117
|
+
spin_grid.addWidget(self.tolerance_field, 0, 1)
|
|
118
|
+
spin_grid.addWidget(self.optimize_contours_label, 1, 0)
|
|
119
|
+
spin_grid.addWidget(self.optimize_contours_field, 1, 1)
|
|
120
|
+
spin_grid.addWidget(self.use_target_upm, 2, 0)
|
|
121
|
+
spin_grid.addWidget(self.target_upm_field, 2, 1)
|
|
122
|
+
spin_grid.setColumnStretch(2, 1)
|
|
123
|
+
options.addLayout(spin_grid)
|
|
124
|
+
|
|
125
|
+
self.upm_warning_label = QLabel("Non-standard UPM. Common values: 1000, 1024, 2048.")
|
|
126
|
+
self.upm_warning_label.setObjectName("warningHint")
|
|
127
|
+
self.upm_warning_label.setWordWrap(True)
|
|
128
|
+
options.addWidget(self.upm_warning_label)
|
|
129
|
+
self.use_target_upm.toggled.connect(self._update_upm_warning)
|
|
130
|
+
self.target_upm.valueChanged.connect(self._update_upm_warning)
|
|
131
|
+
options.addWidget(self.subroutinize)
|
|
132
|
+
options.addWidget(self.autohint)
|
|
133
|
+
|
|
134
|
+
self.format_label = QLabel("Output format:")
|
|
135
|
+
self.format_woff = QCheckBox("WOFF")
|
|
136
|
+
self.format_woff.setChecked(True)
|
|
137
|
+
self.format_woff2 = QCheckBox("WOFF2")
|
|
138
|
+
self.format_woff2.setChecked(True)
|
|
139
|
+
for checkbox in (self.format_woff, self.format_woff2):
|
|
140
|
+
checkbox.toggled.connect(self.compatibilityChanged)
|
|
141
|
+
checkbox.toggled.connect(self.validityChanged)
|
|
142
|
+
self.obfuscate_names = QCheckBox("Obfuscate names")
|
|
143
|
+
self.obfuscate_names.setToolTip(
|
|
144
|
+
"Replace the family, full and PostScript names with hashes, also in the file name."
|
|
145
|
+
)
|
|
146
|
+
self.remove_unused_glyphs = QCheckBox("Remove unused glyphs")
|
|
147
|
+
self.remove_unused_glyphs.setToolTip(
|
|
148
|
+
"Drop the glyphs not reachable from the character map or the OpenType features."
|
|
149
|
+
)
|
|
150
|
+
self.remove_non_windows_names = QCheckBox("Remove non-Windows names")
|
|
151
|
+
self.remove_non_windows_names.setToolTip(
|
|
152
|
+
"Remove the name records whose platform ID is not 3 (e.g. Macintosh records)."
|
|
153
|
+
)
|
|
154
|
+
self.remove_dsig = QCheckBox("Remove DSIG table")
|
|
155
|
+
self.remove_dsig.setToolTip(
|
|
156
|
+
"Remove the digital signature table from WOFF fonts. WOFF2 does not support it."
|
|
157
|
+
)
|
|
158
|
+
self.format_woff.toggled.connect(self._update_dsig_visibility)
|
|
159
|
+
self.css_kit = QCheckBox("Create CSS")
|
|
160
|
+
self.css_kit.setToolTip(
|
|
161
|
+
"Write a fonts.css file with @font-face rules and a class for each OpenType feature."
|
|
162
|
+
)
|
|
163
|
+
formats = QHBoxLayout()
|
|
164
|
+
formats.setSpacing(16)
|
|
165
|
+
formats.addWidget(self.format_label)
|
|
166
|
+
formats.addWidget(self.format_woff)
|
|
167
|
+
formats.addWidget(self.format_woff2)
|
|
168
|
+
formats.addStretch()
|
|
169
|
+
options.addLayout(formats)
|
|
170
|
+
options.addWidget(self.obfuscate_names)
|
|
171
|
+
options.addWidget(self.remove_unused_glyphs)
|
|
172
|
+
options.addWidget(self.remove_non_windows_names)
|
|
173
|
+
options.addWidget(self.remove_dsig)
|
|
174
|
+
options.addWidget(self.css_kit)
|
|
175
|
+
options.addWidget(self.instances_hint)
|
|
176
|
+
|
|
177
|
+
self.no_profile_options_label = QLabel("No additional options for this profile.")
|
|
178
|
+
self.no_profile_options_label.setObjectName("hint")
|
|
179
|
+
self.no_profile_options_label.setWordWrap(True)
|
|
180
|
+
options.addWidget(self.no_profile_options_label)
|
|
181
|
+
self.set_conversion("ttf2otf")
|
|
182
|
+
|
|
183
|
+
def set_conversion(self, conversion: str | None) -> None:
|
|
184
|
+
outline = conversion in ("ttf2otf", "otf2ttf")
|
|
185
|
+
postscript = conversion == "ttf2otf"
|
|
186
|
+
webfont = conversion == "ft2wf"
|
|
187
|
+
self._web_profile = webfont
|
|
188
|
+
variable = conversion == "var2static"
|
|
189
|
+
self._outline_profile = outline
|
|
190
|
+
self.instances_hint.setVisible(variable)
|
|
191
|
+
|
|
192
|
+
# Qu2"uPen (TTF → OTF) rejects a tolerance of zero.
|
|
193
|
+
self.tolerance.setMinimum(0.1 if postscript else 0.0)
|
|
194
|
+
self.tolerance_label.setText("Tolerance (0.1–3.0)" if postscript else "Tolerance (0.0–3.0)")
|
|
195
|
+
self.tolerance_label.setVisible(outline)
|
|
196
|
+
self.tolerance_field.setVisible(outline)
|
|
197
|
+
self.use_target_upm.setVisible(outline or variable)
|
|
198
|
+
self.target_upm_field.setVisible(outline or variable)
|
|
199
|
+
self._variable_profile = variable
|
|
200
|
+
self._update_outline_options(conversion)
|
|
201
|
+
self.format_label.setVisible(webfont)
|
|
202
|
+
self.format_woff.setVisible(webfont)
|
|
203
|
+
self.format_woff2.setVisible(webfont)
|
|
204
|
+
self.obfuscate_names.setVisible(webfont)
|
|
205
|
+
self.remove_unused_glyphs.setVisible(webfont)
|
|
206
|
+
self.remove_non_windows_names.setVisible(webfont)
|
|
207
|
+
self.css_kit.setVisible(webfont)
|
|
208
|
+
self._update_dsig_visibility()
|
|
209
|
+
self.no_profile_options_label.setText(
|
|
210
|
+
"Choose a conversion to see its options."
|
|
211
|
+
if conversion is None
|
|
212
|
+
else "No additional options for this profile."
|
|
213
|
+
)
|
|
214
|
+
self.no_profile_options_label.setVisible(not (outline or webfont or variable))
|
|
215
|
+
self._update_upm_warning()
|
|
216
|
+
|
|
217
|
+
def _update_dsig_visibility(self, *_: object) -> None:
|
|
218
|
+
self.remove_dsig.setVisible(self._web_profile and self.format_woff.isChecked())
|
|
219
|
+
|
|
220
|
+
def set_instance_outlines(self, outlines: set[str]) -> None:
|
|
221
|
+
"""Show only the options that apply to the outlines of the selected variable fonts."""
|
|
222
|
+
if outlines != self._instance_outlines:
|
|
223
|
+
self._instance_outlines = outlines
|
|
224
|
+
if self._variable_profile:
|
|
225
|
+
self._update_outline_options("var2static")
|
|
226
|
+
|
|
227
|
+
def _update_outline_options(self, conversion: str | None) -> None:
|
|
228
|
+
self.optimize_contours_label.setVisible(conversion == "ttf2otf")
|
|
229
|
+
self.optimize_contours_field.setVisible(conversion == "ttf2otf")
|
|
230
|
+
if conversion == "var2static":
|
|
231
|
+
outlines = self._instance_outlines or {"TrueType", "PostScript"}
|
|
232
|
+
self.subroutinize.setVisible("PostScript" in outlines)
|
|
233
|
+
self.autohint.setVisible("TrueType" in outlines)
|
|
234
|
+
self.subroutinize.setText("Subroutinize (PostScript only)")
|
|
235
|
+
self.autohint.setText("Autohint (TrueType only)")
|
|
236
|
+
else:
|
|
237
|
+
self.subroutinize.setVisible(conversion == "ttf2otf")
|
|
238
|
+
self.autohint.setVisible(conversion == "otf2ttf")
|
|
239
|
+
self.subroutinize.setText("Subroutinize")
|
|
240
|
+
self.autohint.setText("Autohint")
|
|
241
|
+
|
|
242
|
+
def selected_web_format(self) -> WebFormat | None:
|
|
243
|
+
woff, woff2 = self.format_woff.isChecked(), self.format_woff2.isChecked()
|
|
244
|
+
if woff and not woff2:
|
|
245
|
+
return "woff"
|
|
246
|
+
if woff2 and not woff:
|
|
247
|
+
return "woff2"
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
def web_format_valid(self) -> bool:
|
|
251
|
+
return self.format_woff.isChecked() or self.format_woff2.isChecked()
|
|
252
|
+
|
|
253
|
+
def settings_for(
|
|
254
|
+
self,
|
|
255
|
+
conversion: str,
|
|
256
|
+
common: ConversionOptions,
|
|
257
|
+
instances: tuple[tuple[Path, tuple[InstanceSpec, ...]], ...] = (),
|
|
258
|
+
) -> ConversionSettings:
|
|
259
|
+
if conversion == "ttf2otf":
|
|
260
|
+
settings: ConversionSettings = TtfToOtfOptions(
|
|
261
|
+
tolerance=self.tolerance.value(),
|
|
262
|
+
target_upm=self.target_upm.value() if self.use_target_upm.isChecked() else None,
|
|
263
|
+
subroutinize=self.subroutinize.isChecked(),
|
|
264
|
+
optimize_contours=self.optimize_contours.value(),
|
|
265
|
+
)
|
|
266
|
+
elif conversion == "otf2ttf":
|
|
267
|
+
settings = OtfToTtfOptions(
|
|
268
|
+
tolerance=self.tolerance.value(),
|
|
269
|
+
target_upm=self.target_upm.value() if self.use_target_upm.isChecked() else None,
|
|
270
|
+
autohint=self.autohint.isChecked(),
|
|
271
|
+
)
|
|
272
|
+
elif conversion == "ft2wf":
|
|
273
|
+
settings = SfntToWebOptions(
|
|
274
|
+
format=self.selected_web_format(),
|
|
275
|
+
obfuscate_names=self.obfuscate_names.isChecked(),
|
|
276
|
+
remove_unused_glyphs=self.remove_unused_glyphs.isChecked(),
|
|
277
|
+
remove_non_windows_names=self.remove_non_windows_names.isChecked(),
|
|
278
|
+
css_kit=self.css_kit.isChecked(),
|
|
279
|
+
remove_dsig=self.remove_dsig.isChecked() and self.format_woff.isChecked(),
|
|
280
|
+
)
|
|
281
|
+
elif conversion == "woff2ft":
|
|
282
|
+
settings = WoffToSfntOptions()
|
|
283
|
+
elif conversion == "woff22ft":
|
|
284
|
+
settings = Woff2ToSfntOptions()
|
|
285
|
+
elif conversion == "ttc2sfnt":
|
|
286
|
+
settings = TtcToSfntOptions()
|
|
287
|
+
elif conversion == "var2static":
|
|
288
|
+
settings = VarToStaticOptions(
|
|
289
|
+
instances=instances,
|
|
290
|
+
target_upm=self.target_upm.value() if self.use_target_upm.isChecked() else None,
|
|
291
|
+
autohint=self.autohint.isChecked(),
|
|
292
|
+
subroutinize=self.subroutinize.isChecked(),
|
|
293
|
+
)
|
|
294
|
+
else:
|
|
295
|
+
raise ValueError(f"Unsupported conversion profile: {conversion}")
|
|
296
|
+
|
|
297
|
+
return replace(
|
|
298
|
+
settings,
|
|
299
|
+
recursive=common.recursive,
|
|
300
|
+
output_dir=common.output_dir,
|
|
301
|
+
overwrite=common.overwrite,
|
|
302
|
+
recalc_bboxes=common.recalc_bboxes,
|
|
303
|
+
recalc_timestamp=common.recalc_timestamp,
|
|
304
|
+
reorder_tables=common.reorder_tables,
|
|
305
|
+
organize_output=common.organize_output,
|
|
306
|
+
organize_by_family=common.organize_by_family,
|
|
307
|
+
organization_levels=common.organization_levels,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
def _update_upm_warning(self, *_: object) -> None:
|
|
311
|
+
non_standard = (
|
|
312
|
+
self.use_target_upm.isChecked() and self.target_upm.value() not in UPM_STEP_VALUES
|
|
313
|
+
)
|
|
314
|
+
self.upm_warning_label.setVisible(
|
|
315
|
+
(self._outline_profile or self._variable_profile) and non_standard
|
|
316
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Presentation labels for the converter's supported conversion profiles."""
|
|
2
|
+
|
|
3
|
+
CONVERSIONS: dict[str, str] = {
|
|
4
|
+
"ttf2otf": "TrueType → PostScript (TTF → OTF)",
|
|
5
|
+
"otf2ttf": "PostScript → TrueType (OTF → TTF)",
|
|
6
|
+
"ft2wf": "SFNT → WOFF / WOFF2",
|
|
7
|
+
"woff2ft": "WOFF → SFNT",
|
|
8
|
+
"woff22ft": "WOFF2 → SFNT",
|
|
9
|
+
"ttc2sfnt": "TrueType Collection → SFNT",
|
|
10
|
+
"var2static": "Variable → Static (instances)",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
CONVERSION_GROUP_HEADINGS: dict[str, str] = {
|
|
14
|
+
"ttf2otf": "Outlines",
|
|
15
|
+
"ft2wf": "Web fonts",
|
|
16
|
+
"ttc2sfnt": "Other",
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from PySide6.QtCore import QThread, Signal
|
|
4
|
+
|
|
5
|
+
from font_converter.inspection import inspect_font
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ScanWorker(QThread):
|
|
9
|
+
"""Lists the candidate files of the sources and reads their font metadata."""
|
|
10
|
+
|
|
11
|
+
# (done, total); total is 0 while the files are still being listed.
|
|
12
|
+
progress = Signal(int, int)
|
|
13
|
+
font_found = Signal(object, object)
|
|
14
|
+
|
|
15
|
+
def __init__(self, sources: list[Path], recursive: bool) -> None:
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.sources = sources
|
|
18
|
+
self.recursive = recursive
|
|
19
|
+
|
|
20
|
+
def run(self) -> None:
|
|
21
|
+
self.progress.emit(0, 0)
|
|
22
|
+
files: dict[Path, None] = {}
|
|
23
|
+
for source in self.sources:
|
|
24
|
+
if source.is_file():
|
|
25
|
+
files[source] = None
|
|
26
|
+
elif source.is_dir():
|
|
27
|
+
candidates = source.rglob("*") if self.recursive else source.glob("*")
|
|
28
|
+
for path in candidates:
|
|
29
|
+
if self.isInterruptionRequested():
|
|
30
|
+
return
|
|
31
|
+
if path.is_file():
|
|
32
|
+
files[path] = None
|
|
33
|
+
total = len(files)
|
|
34
|
+
self.progress.emit(0, total)
|
|
35
|
+
for done, path in enumerate(files, start=1):
|
|
36
|
+
if self.isInterruptionRequested():
|
|
37
|
+
return
|
|
38
|
+
info = inspect_font(path)
|
|
39
|
+
if info is not None:
|
|
40
|
+
self.font_found.emit(path, info)
|
|
41
|
+
if done % 20 == 0 or done == total:
|
|
42
|
+
self.progress.emit(done, total)
|