diff --git a/src/__init__.py b/src/__init__.py index 000c2a23c..d8be4e9b2 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -943,6 +943,7 @@ def file_info(self): fs = mupdf.pdf_dict_get(annot_obj, PDF_NAME('FS')) + filename = None o = mupdf.pdf_dict_get(fs, PDF_NAME('UF')) if o.m_internal: filename = mupdf.pdf_to_text_string(o) @@ -2053,7 +2054,7 @@ def make_subarch(entries, mount, fmt): raise ValueError(f'Not a file or directory: {content!r}') elif is_binary_data(content): - assert isinstance(path, str) and path != '' \ + assert isinstance(path, str) and path != '', \ f'Need name for binary content, but {path=}.' self._add_treeitem(content, path) return make_subarch([path], None, 'tree') @@ -9482,6 +9483,8 @@ def on_state(self): if bstate is None: bstate = dict() for k in bstate.keys(): + if bstate[k] is None: + continue for v in bstate[k]: if v != "Off": return v @@ -13140,7 +13143,7 @@ def set_language(self, language=None): lang = mupdf.fz_text_language_from_string(language) assert hasattr(mupdf, 'fz_string_from_text_language2') mupdf.pdf_dict_put_text_string( - pdfpage.obj, + pdfpage.obj(), PDF_NAME('Lang'), mupdf.fz_string_from_text_language2(lang) ) @@ -14179,7 +14182,7 @@ def tobytes(self, output="png", jpg_quality=95): if idx is None: raise ValueError(f"Image format {output} not in {tuple(valid_formats.keys())}") if self.alpha and idx in (2, 6, 7): - raise ValueError("'{output}' cannot have alpha") + raise ValueError(f"'{output}' cannot have alpha") if self.colorspace and self.colorspace.n > 3 and idx in (1, 2, 4): raise ValueError(f"unsupported colorspace for '{output}'") if idx == 7: @@ -20996,7 +20999,7 @@ def JM_matrix_from_py(m): for i in range(6): a[i] = JM_FLOAT_ITEM(m, i) if a[i] is None: - return mupdf.FzRect() + return mupdf.FzMatrix() return mupdf.FzMatrix(a[0], a[1], a[2], a[3], a[4], a[5]) diff --git a/src/_apply_pages.py b/src/_apply_pages.py index 5d473db4c..0af40652b 100644 --- a/src/_apply_pages.py +++ b/src/_apply_pages.py @@ -137,11 +137,12 @@ def childfn(): while 1: if verbose: pymupdf.log(f'{os.getpid()=}: calling get().') - page_num = queue_down.get() + item = queue_down.get() if verbose: - pymupdf.log(f'{os.getpid()=}: {page_num=}.') - if page_num is None: + pymupdf.log(f'{os.getpid()=}: {item=}.') + if item is None: break + index, page_num = item try: if not document: if stats: @@ -172,9 +173,9 @@ def childfn(): if verbose: pymupdf.log(f'{os.getpid()=}: exception {e=}') ret = e if verbose: - pymupdf.log(f'{os.getpid()=}: sending {page_num=} {ret=}') - - queue_up.put( (page_num, ret) ) + pymupdf.log(f'{os.getpid()=}: sending {index=} {ret=}') + + queue_up.put( (index, ret) ) error = None @@ -206,8 +207,8 @@ def childfn(): t = time.time() if verbose: pymupdf.log(f'Sending page numbers.') - for page_num in range(len(pages)): - queue_down.put(page_num) + for index, page_num in enumerate(pages): + queue_down.put((index, page_num)) if stats: _stats_write(t, 'Send page numbers') @@ -215,15 +216,15 @@ def childfn(): # of text, but this hasn't been tested. ret = [None] * len(pages) for i in range(len(pages)): - page_num, text = queue_up.get() + index, text = queue_up.get() if verbose: - pymupdf.log(f'{page_num=} {len(text)=}') - assert ret[page_num] is None + pymupdf.log(f'{index=} {len(text)=}') + assert ret[index] is None if isinstance(text, Exception): if not error: error = text break - ret[page_num] = text + ret[index] = text # Close queue. This should cause exception in workers and terminate # them, but on macos-arm64 this does not seem to happen, so we also diff --git a/src/table.py b/src/table.py index 7b8e2c19c..8bbd17b2b 100644 --- a/src/table.py +++ b/src/table.py @@ -196,12 +196,15 @@ def rect_in_rect(inner, outer): def chars_in_rect(CHARS, rect): """Check whether any of the chars in CHAR are inside rectangle 'rect'.""" + # NB: 'rect' (e.g. from page.get_drawings()) and c["x0"]/c["x1"] are in + # top-down page space; c["top"]/c["bottom"] are the top-down counterparts + # of c["y0"]/c["y1"], which are in PDF-native (bottom-up) space instead. return any( 1 and rect[0] <= c["x0"] and c["x1"] <= rect[2] - and rect[1] <= c["y0"] - and rect[3] >= c["y1"] + and rect[1] <= c["top"] + and rect[3] >= c["bottom"] for c in CHARS ) diff --git a/src/utils.py b/src/utils.py index 7d3271ea8..1686ebbba 100644 --- a/src/utils.py +++ b/src/utils.py @@ -210,7 +210,7 @@ def line_text(clip, line): lrect |= r # update line bbox # convert distance to previous word to multiple spaces dist = max( - int(round((r.x0 - x1) / r.width * len(t))), + int(round((r.x0 - x1) / r.width * len(t))) if r.width else 0, 0 if (x1 == clip.x0 or r.x0 <= x1) else 1, ) # number of space characters @@ -498,8 +498,6 @@ def get_text( } option = option.lower() assert option in formats - if option not in formats: - option = "text" if flags is None: flags = formats[option] @@ -962,7 +960,10 @@ def get_label_pno(pgNo, labels): """ # Jorj McKie, 2021-01-06 - item = [x for x in labels if x[0] <= pgNo][-1] + candidates = [x for x in labels if x[0] <= pgNo] + if not candidates: + return "" + item = candidates[-1] rule = rule_dict(item) prefix = rule.get("prefix", "") style = rule.get("style", "")