class PDFColorSpace:
    def __init__(self, name: str, ncomponents: int) -> None:
        self.name = name
        self.ncomponents = ncomponents

    def __repr__(self) -> str:
        return "<PDFColorSpace: %s, ncomponents=%d>" % (self.name, self.ncomponents) class PDFFont:
    def __init__(
        self,
        descriptor: Mapping[str, Any],
        widths: FontWidthDict,
        default_width: Optional[float] = None,
    ) -> None:
        self.descriptor = descriptor
        self.widths: FontWidthDict = resolve_all(widths)
        self.fontname = resolve1(descriptor.get("FontName", "unknown"))
        if isinstance(self.fontname, PSLiteral):
            self.fontname = literal_name(self.fontname)
        self.flags = int_value(descriptor.get("Flags", 0))
        self.ascent = num_value(descriptor.get("Ascent", 0))
        self.descent = num_value(descriptor.get("Descent", 0))
        self.italic_angle = num_value(descriptor.get("ItalicAngle", 0))
        if default_width is None:
            self.default_width = num_value(descriptor.get("MissingWidth", 0))
        else:
            self.default_width = default_width
        self.leading = num_value(descriptor.get("Leading", 0))
        self.bbox = cast(
            Rect, list_value(resolve_all(descriptor.get("FontBBox", (0, 0, 0, 0))))
        )
        self.hscale = self.vscale = 0.001

        # PDF RM 9.8.1 specifies /Descent should always be a negative number.
        # PScript5.dll seems to produce Descent with a positive number, but
        # text analysis will be wrong if this is taken as correct. So force
        # descent to negative.
        if self.descent > 0:
            self.descent = -self.descent
        return

    def __repr__(self) -> str:
        return "<PDFFont>"

    def is_vertical(self) -> bool:
        return False

    def is_multibyte(self) -> bool:
        return False

    def decode(self, bytes: bytes) -> Iterable[int]:
        return bytearray(bytes)  # map(ord, bytes)

    def get_ascent(self) -> float:
        """Ascent above the baseline, in text space units"""
        return self.ascent * self.vscale

    def get_descent(self) -> float:
        """Descent below the baseline, in text space units; always negative"""
        return self.descent * self.vscale

    def get_width(self) -> float:
        w = self.bbox[2] - self.bbox[0]
        if w == 0:
            w = -self.default_width
        return w * self.hscale

    def get_height(self) -> float:
        h = self.bbox[3] - self.bbox[1]
        if h == 0:
            h = self.ascent - self.descent
        return h * self.vscale

    def char_width(self, cid: int) -> float:
        # Because character widths may be mapping either IDs or strings,
        # we try to lookup the character ID first, then its str equivalent.
        try:
            return cast(Dict[int, float], self.widths)[cid] * self.hscale
        except KeyError:
            str_widths = cast(Dict[str, float], self.widths)
            try:
                return str_widths[self.to_unichr(cid)] * self.hscale
            except (KeyError, PDFUnicodeNotDefined):
                return self.default_width * self.hscale

    def char_disp(self, cid: int) -> Union[float, Tuple[Optional[float], float]]:
        "Returns an integer for horizontal fonts, a tuple for vertical fonts."
        return 0

    def string_width(self, s: bytes) -> float:
        return sum(self.char_width(cid) for cid in self.decode(s))

    def to_unichr(self, cid: int) -> str:
        raise NotImplementedError class PDFResourceError(PDFException):
class PDFInterpreterError(PDFException):
class PDFTextState:
class PDFGraphicState:
class PDFResourceManager:
class PDFContentParser(PSStackParser[Union[PSKeyword, PDFStream]]):
class PDFPageInterpreter:
LITERAL_PDF = LIT("PDF")
LITERAL_TEXT = LIT("Text")
LITERAL_FONT = LIT("Font")
LITERAL_FORM = LIT("Form")
LITERAL_IMAGE = LIT("Image")
    KEYWORD_BI = KWD(b"BI")
    KEYWORD_ID = KWD(b"ID")
    KEYWORD_EI = KWD(b"EI")
    def __init__(self) -> None:
    def __repr__(self) -> str:
    def copy(self) -> "PDFTextState":
    def reset(self) -> None:
    def __init__(self) -> None:
    def copy(self) -> "PDFGraphicState":
    def __repr__(self) -> str:
    def __init__(self, caching: bool = True) -> None:
    def get_procset(self, procs: Sequence[object]) -> None:
    def get_cmap(self, cmapname: str, strict: bool = False) -> CMapBase:
    def get_font(self, objid: object, spec: Mapping[str, object]) -> PDFFont:
    def __init__(self, streams: Sequence[object]) -> None:
    def fillfp(self) -> None:
    def seek(self, pos: int) -> None:
    def fillbuf(self) -> None:
    def get_inline_data(self, pos: int, target: bytes = b"EI") -> Tuple[int, bytes]:
    def flush(self) -> None:
    def do_keyword(self, pos: int, token: PSKeyword) -> None:
    def __init__(self, rsrcmgr: PDFResourceManager, device: PDFDevice) -> None:
    def dup(self) -> "PDFPageInterpreter":
    def init_resources(self, resources: Dict[object, object]) -> None:
        def get_colorspace(spec: object) -> Optional[PDFColorSpace]:
    def init_state(self, ctm: Matrix) -> None:
    def push(self, obj: PDFStackT) -> None:
    def pop(self, n: int) -> List[PDFStackT]:
    def get_current_state(self) -> Tuple[Matrix, PDFTextState, PDFGraphicState]:
    def set_current_state(
        self, state: Tuple[Matrix, PDFTextState, PDFGraphicState]
    ) -> None:
    def do_q(self) -> None:
    def do_Q(self) -> None:
    def do_cm(
        self,
        a1: PDFStackT,
        b1: PDFStackT,
        c1: PDFStackT,
        d1: PDFStackT,
        e1: PDFStackT,
        f1: PDFStackT,
    ) -> None:
    def do_w(self, linewidth: PDFStackT) -> None:
    def do_J(self, linecap: PDFStackT) -> None:
    def do_j(self, linejoin: PDFStackT) -> None:
    def do_M(self, miterlimit: PDFStackT) -> None:
    def do_d(self, dash: PDFStackT, phase: PDFStackT) -> None:
    def do_ri(self, intent: PDFStackT) -> None:
    def do_i(self, flatness: PDFStackT) -> None:
    def do_gs(self, name: PDFStackT) -> None:
    def do_m(self, x: PDFStackT, y: PDFStackT) -> None:
    def do_l(self, x: PDFStackT, y: PDFStackT) -> None:
    def do_c(
        self,
        x1: PDFStackT,
        y1: PDFStackT,
        x2: PDFStackT,
        y2: PDFStackT,
        x3: PDFStackT,
        y3: PDFStackT,
    ) -> None:
    def do_v(self, x2: PDFStackT, y2: PDFStackT, x3: PDFStackT, y3: PDFStackT) -> None:
    def do_y(self, x1: PDFStackT, y1: PDFStackT, x3: PDFStackT, y3: PDFStackT) -> None:
    def do_h(self) -> None:
    def do_re(self, x: PDFStackT, y: PDFStackT, w: PDFStackT, h: PDFStackT) -> None:
    def do_S(self) -> None:
    def do_s(self) -> None:
    def do_f(self) -> None:
    def do_F(self) -> None:
    def do_f_a(self) -> None:
    def do_B(self) -> None:
    def do_B_a(self) -> None:
    def do_b(self) -> None:
    def do_b_a(self) -> None:
    def do_n(self) -> None:
    def do_W(self) -> None:
    def do_W_a(self) -> None:
    def do_CS(self, name: PDFStackT) -> None:
    def do_cs(self, name: PDFStackT) -> None:
    def do_G(self, gray: PDFStackT) -> None:
    def do_g(self, gray: PDFStackT) -> None:
    def do_RG(self, r: PDFStackT, g: PDFStackT, b: PDFStackT) -> None:
    def do_rg(self, r: PDFStackT, g: PDFStackT, b: PDFStackT) -> None:
    def do_K(self, c: PDFStackT, m: PDFStackT, y: PDFStackT, k: PDFStackT) -> None:
    def do_k(self, c: PDFStackT, m: PDFStackT, y: PDFStackT, k: PDFStackT) -> None:
    def do_SCN(self) -> None:
    def do_scn(self) -> None:
    def do_SC(self) -> None:
    def do_sc(self) -> None:
    def do_sh(self, name: object) -> None:
    def do_BT(self) -> None:
    def do_ET(self) -> None:
    def do_BX(self) -> None:
    def do_EX(self) -> None:
    def do_MP(self, tag: PDFStackT) -> None:
    def do_DP(self, tag: PDFStackT, props: PDFStackT) -> None:
    def do_BMC(self, tag: PDFStackT) -> None:
    def do_BDC(self, tag: PDFStackT, props: PDFStackT) -> None:
    def do_EMC(self) -> None:
    def do_Tc(self, space: PDFStackT) -> None:
    def do_Tw(self, space: PDFStackT) -> None:
    def do_Tz(self, scale: PDFStackT) -> None:
    def do_TL(self, leading: PDFStackT) -> None:
    def do_Tf(self, fontid: PDFStackT, fontsize: PDFStackT) -> None:
    def do_Tr(self, render: PDFStackT) -> None:
    def do_Ts(self, rise: PDFStackT) -> None:
    def do_Td(self, tx: PDFStackT, ty: PDFStackT) -> None:
    def do_TD(self, tx: PDFStackT, ty: PDFStackT) -> None:
    def do_Tm(
        self,
        a: PDFStackT,
        b: PDFStackT,
        c: PDFStackT,
        d: PDFStackT,
        e: PDFStackT,
        f: PDFStackT,
    ) -> None:
    def do_T_a(self) -> None:
    def do_TJ(self, seq: PDFStackT) -> None:
    def do_Tj(self, s: PDFStackT) -> None:
    def do__q(self, s: PDFStackT) -> None:
    def do__w(self, aw: PDFStackT, ac: PDFStackT, s: PDFStackT) -> None:
    def do_BI(self) -> None:
    def do_ID(self) -> None:
    def do_EI(self, obj: PDFStackT) -> None:
    def do_Do(self, xobjid_arg: PDFStackT) -> None:
    def process_page(self, page: PDFPage) -> None:
    def render_contents(
        self,
        resources: Dict[object, object],
        streams: Sequence[object],
        ctm: Matrix = MATRIX_IDENTITY,
    ) -> None:
    def execute(self, streams: Sequence[object]) -> None: class PDFGraphicState:
    def __init__(self) -> None:
        self.linewidth: float = 0
        self.linecap: Optional[object] = None
        self.linejoin: Optional[object] = None
        self.miterlimit: Optional[object] = None
        self.dash: Optional[Tuple[object, object]] = None
        self.intent: Optional[object] = None
        self.flatness: Optional[object] = None

        # stroking color
        self.scolor: Optional[Color] = None

        # non stroking color
        self.ncolor: Optional[Color] = None

    def copy(self) -> "PDFGraphicState":
        obj = PDFGraphicState()
        obj.linewidth = self.linewidth
        obj.linecap = self.linecap
        obj.linejoin = self.linejoin
        obj.miterlimit = self.miterlimit
        obj.dash = self.dash
        obj.intent = self.intent
        obj.flatness = self.flatness
        obj.scolor = self.scolor
        obj.ncolor = self.ncolor
        return obj

    def __repr__(self) -> str:
        return (
            "<PDFGraphicState: linewidth=%r, linecap=%r, linejoin=%r, "
            " miterlimit=%r, dash=%r, intent=%r, flatness=%r, "
            " stroking color=%r, non stroking color=%r>"
            % (
                self.linewidth,
                self.linecap,
                self.linejoin,
                self.miterlimit,
                self.dash,
                self.intent,
                self.flatness,
                self.scolor,
                self.ncolor,
            )
        ) class PDFStream(PDFObject):
    def __init__(
        self,
        attrs: Dict[str, Any],
        rawdata: bytes,
        decipher: Optional[DecipherCallable] = None,
    ) -> None:
        assert isinstance(attrs, dict), str(type(attrs))
        self.attrs = attrs
        self.rawdata: Optional[bytes] = rawdata
        self.decipher = decipher
        self.data: Optional[bytes] = None
        self.objid: Optional[int] = None
        self.genno: Optional[int] = None

    def set_objid(self, objid: int, genno: int) -> None:
        self.objid = objid
        self.genno = genno

    def __repr__(self) -> str:
        if self.data is None:
            assert self.rawdata is not None
            return "<PDFStream(%r): raw=%d, %r>" % (
                self.objid,
                len(self.rawdata),
                self.attrs,
            )
        else:
            assert self.data is not None
            return "<PDFStream(%r): len=%d, %r>" % (
                self.objid,
                len(self.data),
                self.attrs,
            )

    def __contains__(self, name: object) -> bool:
        return name in self.attrs

    def __getitem__(self, name: str) -> Any:
        return self.attrs[name]

    def get(self, name: str, default: object = None) -> Any:
        return self.attrs.get(name, default)

    def get_any(self, names: Iterable[str], default: object = None) -> Any:
        for name in names:
            if name in self.attrs:
                return self.attrs[name]
        return default

    def get_filters(self) -> List[Tuple[Any, Any]]:
        filters = self.get_any(("F", "Filter"))
        params = self.get_any(("DP", "DecodeParms", "FDecodeParms"), {})
        if not filters:
            return []
        if not isinstance(filters, list):
            filters = [filters]
        if not isinstance(params, list):
            # Make sure the parameters list is the same as filters.
            params = [params] * len(filters)
        if settings.STRICT and len(params) != len(filters):
            raise PDFException("Parameters len filter mismatch")
        # resolve filter if possible
        _filters = []
        for fltr in filters:
            if hasattr(fltr, "resolve"):
                fltr = fltr.resolve()[0]
            _filters.append(fltr)
        # return list solves https://github.com/pdfminer/pdfminer.six/issues/15
        return list(zip(_filters, params))

    def decode(self) -> None:
        assert self.data is None and self.rawdata is not None, str(
            (self.data, self.rawdata)
        )
        data = self.rawdata
        if self.decipher:
            # Handle encryption
            assert self.objid is not None
            assert self.genno is not None
            data = self.decipher(self.objid, self.genno, data, self.attrs)
        filters = self.get_filters()
        if not filters:
            self.data = data
            self.rawdata = None
            return
        for (f, params) in filters:
            if f in LITERALS_FLATE_DECODE:
                # will get errors if the document is encrypted.
                try:
                    data = zlib.decompress(data)

                except zlib.error as e:
                    if settings.STRICT:
                        error_msg = "Invalid zlib bytes: {!r}, {!r}".format(e, data)
                        raise PDFException(error_msg)

                    try:
                        data = decompress_corrupted(data)
                    except zlib.error:
                        data = b""

            elif f in LITERALS_LZW_DECODE:
                data = lzwdecode(data)
            elif f in LITERALS_ASCII85_DECODE:
                data = ascii85decode(data)
            elif f in LITERALS_ASCIIHEX_DECODE:
                data = asciihexdecode(data)
            elif f in LITERALS_RUNLENGTH_DECODE:
                data = rldecode(data)
            elif f in LITERALS_CCITTFAX_DECODE:
                data = ccittfaxdecode(data, params)
            elif f in LITERALS_DCT_DECODE:
                # This is probably a JPG stream
                # it does not need to be decoded twice.
                # Just return the stream to the user.
                pass
            elif f in LITERALS_JBIG2_DECODE:
                pass
            elif f in LITERALS_JPX_DECODE:
                pass
            elif f == LITERAL_CRYPT:
                # not yet..
                raise PDFNotImplementedError("/Crypt filter is unsupported")
            else:
                raise PDFNotImplementedError("Unsupported filter: %r" % f)
            # apply predictors
            if params and "Predictor" in params:
                pred = int_value(params["Predictor"])
                if pred == 1:
                    # no predictor
                    pass
                elif 10 <= pred:
                    # PNG predictor
                    colors = int_value(params.get("Colors", 1))
                    columns = int_value(params.get("Columns", 1))
                    raw_bits_per_component = params.get("BitsPerComponent", 8)
                    bitspercomponent = int_value(raw_bits_per_component)
                    data = apply_png_predictor(
                        pred, colors, columns, bitspercomponent, data
                    )
                else:
                    error_msg = "Unsupported predictor: %r" % pred
                    raise PDFNotImplementedError(error_msg)
        self.data = data
        self.rawdata = None
        return

    def get_data(self) -> bytes:
        if self.data is None:
            self.decode()
            assert self.data is not None
        return self.data

    def get_rawdata(self) -> Optional[bytes]:
        return self.rawdata INF = (1 << 31) - 1 INF = (1 << 31) - 1
MATRIX_IDENTITY: Matrix = (1, 0, 0, 1, 0, 0)
_T = TypeVar("_T")
ROMAN_ONES = ["i", "x", "c", "m"]
ROMAN_FIVES = ["v", "l", "d"]
class open_filename(object):
class Plane(Generic[LTComponentT]):
    def __init__(self, filename: FileOrName, *args: Any, **kwargs: Any) -> None:
    def __enter__(self) -> AnyIO:
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
def make_compat_bytes(in_str: str) -> bytes:
def make_compat_str(o: object) -> str:
def shorten_str(s: str, size: int) -> str:
def compatible_encode_method(
    bytesorstring: Union[bytes, str], encoding: str = "utf-8", erraction: str = "ignore"
) -> str:
def paeth_predictor(left: int, above: int, upper_left: int) -> int:
def apply_png_predictor(
    pred: int, colors: int, columns: int, bitspercomponent: int, data: bytes
) -> bytes:
def mult_matrix(m1: Matrix, m0: Matrix) -> Matrix:
def translate_matrix(m: Matrix, v: Point) -> Matrix:
def apply_matrix_pt(m: Matrix, v: Point) -> Point:
def apply_matrix_norm(m: Matrix, v: Point) -> Point:
def isnumber(x: object) -> bool:
def uniq(objs: Iterable[_T]) -> Iterator[_T]:
def fsplit(pred: Callable[[_T], bool], objs: Iterable[_T]) -> Tuple[List[_T], List[_T]]:
def drange(v0: float, v1: float, d: int) -> range:
def get_bound(pts: Iterable[Point]) -> Rect:
def pick(
    seq: Iterable[_T], func: Callable[[_T], float], maxobj: Optional[_T] = None
) -> Optional[_T]:
def choplist(n: int, seq: Iterable[_T]) -> Iterator[Tuple[_T, ...]]:
def nunpack(s: bytes, default: int = 0) -> int:
def decode_text(s: bytes) -> str:
def enc(x: str) -> str:
def bbox2str(bbox: Rect) -> str:
def matrix2str(m: Matrix) -> str:
def vecBetweenBoxes(obj1: "LTComponent", obj2: "LTComponent") -> Point:
    def __init__(self, bbox: Rect, gridsize: int = 50) -> None:
    def __repr__(self) -> str:
    def __iter__(self) -> Iterator[LTComponentT]:
    def __len__(self) -> int:
    def __contains__(self, obj: object) -> bool:
    def _getrange(self, bbox: Rect) -> Iterator[Point]:
    def extend(self, objs: Iterable[LTComponentT]) -> None:
    def add(self, obj: LTComponentT) -> None:
    def remove(self, obj: LTComponentT) -> None:
    def find(self, bbox: Rect) -> Iterator[LTComponentT]:
def format_int_roman(value: int) -> str:
def format_int_alpha(value: int) -> str: INF = (1 << 31) - 1
MATRIX_IDENTITY: Matrix = (1, 0, 0, 1, 0, 0)
_T = TypeVar("_T")
ROMAN_ONES = ["i", "x", "c", "m"]
ROMAN_FIVES = ["v", "l", "d"]
class open_filename(object):
class Plane(Generic[LTComponentT]):
    def __init__(self, filename: FileOrName, *args: Any, **kwargs: Any) -> None:
    def __enter__(self) -> AnyIO:
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
def make_compat_bytes(in_str: str) -> bytes:
def make_compat_str(o: object) -> str:
def shorten_str(s: str, size: int) -> str:
def compatible_encode_method(
    bytesorstring: Union[bytes, str], encoding: str = "utf-8", erraction: str = "ignore"
) -> str:
def paeth_predictor(left: int, above: int, upper_left: int) -> int:
def apply_png_predictor(
    pred: int, colors: int, columns: int, bitspercomponent: int, data: bytes
) -> bytes:
def mult_matrix(m1: Matrix, m0: Matrix) -> Matrix:
def translate_matrix(m: Matrix, v: Point) -> Matrix:
def apply_matrix_pt(m: Matrix, v: Point) -> Point:
def apply_matrix_norm(m: Matrix, v: Point) -> Point:
def isnumber(x: object) -> bool:
def uniq(objs: Iterable[_T]) -> Iterator[_T]:
def fsplit(pred: Callable[[_T], bool], objs: Iterable[_T]) -> Tuple[List[_T], List[_T]]:
def drange(v0: float, v1: float, d: int) -> range:
def get_bound(pts: Iterable[Point]) -> Rect:
def pick(
    seq: Iterable[_T], func: Callable[[_T], float], maxobj: Optional[_T] = None
) -> Optional[_T]:
def choplist(n: int, seq: Iterable[_T]) -> Iterator[Tuple[_T, ...]]:
def nunpack(s: bytes, default: int = 0) -> int:
def decode_text(s: bytes) -> str:
def enc(x: str) -> str:
def bbox2str(bbox: Rect) -> str:
def matrix2str(m: Matrix) -> str:
def vecBetweenBoxes(obj1: "LTComponent", obj2: "LTComponent") -> Point:
    def __init__(self, bbox: Rect, gridsize: int = 50) -> None:
    def __repr__(self) -> str:
    def __iter__(self) -> Iterator[LTComponentT]:
    def __len__(self) -> int:
    def __contains__(self, obj: object) -> bool:
    def _getrange(self, bbox: Rect) -> Iterator[Point]:
    def extend(self, objs: Iterable[LTComponentT]) -> None:
    def add(self, obj: LTComponentT) -> None:
    def remove(self, obj: LTComponentT) -> None:
    def find(self, bbox: Rect) -> Iterator[LTComponentT]:
def format_int_roman(value: int) -> str:
def format_int_alpha(value: int) -> str: class Plane(Generic[LTComponentT]):
    """A set-like data structure for objects placed on a plane.

    Can efficiently find objects in a certain rectangular area.
    It maintains two parallel lists of objects, each of
    which is sorted by its x or y coordinate.
    """

    def __init__(self, bbox: Rect, gridsize: int = 50) -> None:
        self._seq: List[LTComponentT] = []  # preserve the object order.
        self._objs: Set[LTComponentT] = set()
        self._grid: Dict[Point, List[LTComponentT]] = {}
        self.gridsize = gridsize
        (self.x0, self.y0, self.x1, self.y1) = bbox

    def __repr__(self) -> str:
        return "<Plane objs=%r>" % list(self)

    def __iter__(self) -> Iterator[LTComponentT]:
        return (obj for obj in self._seq if obj in self._objs)

    def __len__(self) -> int:
        return len(self._objs)

    def __contains__(self, obj: object) -> bool:
        return obj in self._objs

    def _getrange(self, bbox: Rect) -> Iterator[Point]:
        (x0, y0, x1, y1) = bbox
        if x1 <= self.x0 or self.x1 <= x0 or y1 <= self.y0 or self.y1 <= y0:
            return
        x0 = max(self.x0, x0)
        y0 = max(self.y0, y0)
        x1 = min(self.x1, x1)
        y1 = min(self.y1, y1)
        for grid_y in drange(y0, y1, self.gridsize):
            for grid_x in drange(x0, x1, self.gridsize):
                yield (grid_x, grid_y)

    def extend(self, objs: Iterable[LTComponentT]) -> None:
        for obj in objs:
            self.add(obj)

    def add(self, obj: LTComponentT) -> None:
        """place an object."""
        for k in self._getrange((obj.x0, obj.y0, obj.x1, obj.y1)):
            if k not in self._grid:
                r: List[LTComponentT] = []
                self._grid[k] = r
            else:
                r = self._grid[k]
            r.append(obj)
        self._seq.append(obj)
        self._objs.add(obj)

    def remove(self, obj: LTComponentT) -> None:
        """displace an object."""
        for k in self._getrange((obj.x0, obj.y0, obj.x1, obj.y1)):
            try:
                self._grid[k].remove(obj)
            except (KeyError, ValueError):
                pass
        self._objs.remove(obj)

    def find(self, bbox: Rect) -> Iterator[LTComponentT]:
        """finds objects that are in a certain area."""
        (x0, y0, x1, y1) = bbox
        done = set()
        for k in self._getrange(bbox):
            if k not in self._grid:
                continue
            for obj in self._grid[k]:
                if obj in done:
                    continue
                done.add(obj)
                if obj.x1 <= x0 or x1 <= obj.x0 or obj.y1 <= y0 or y1 <= obj.y0:
                    continue
                yield obj INF = (1 << 31) - 1
MATRIX_IDENTITY: Matrix = (1, 0, 0, 1, 0, 0)
_T = TypeVar("_T")
ROMAN_ONES = ["i", "x", "c", "m"]
ROMAN_FIVES = ["v", "l", "d"]
class open_filename(object):
class Plane(Generic[LTComponentT]):
    def __init__(self, filename: FileOrName, *args: Any, **kwargs: Any) -> None:
    def __enter__(self) -> AnyIO:
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
def make_compat_bytes(in_str: str) -> bytes:
def make_compat_str(o: object) -> str:
def shorten_str(s: str, size: int) -> str:
def compatible_encode_method(
    bytesorstring: Union[bytes, str], encoding: str = "utf-8", erraction: str = "ignore"
) -> str:
def paeth_predictor(left: int, above: int, upper_left: int) -> int:
def apply_png_predictor(
    pred: int, colors: int, columns: int, bitspercomponent: int, data: bytes
) -> bytes:
def mult_matrix(m1: Matrix, m0: Matrix) -> Matrix:
def translate_matrix(m: Matrix, v: Point) -> Matrix:
def apply_matrix_pt(m: Matrix, v: Point) -> Point:
def apply_matrix_norm(m: Matrix, v: Point) -> Point:
def isnumber(x: object) -> bool:
def uniq(objs: Iterable[_T]) -> Iterator[_T]:
def fsplit(pred: Callable[[_T], bool], objs: Iterable[_T]) -> Tuple[List[_T], List[_T]]:
def drange(v0: float, v1: float, d: int) -> range:
def get_bound(pts: Iterable[Point]) -> Rect:
def pick(
    seq: Iterable[_T], func: Callable[[_T], float], maxobj: Optional[_T] = None
) -> Optional[_T]:
def choplist(n: int, seq: Iterable[_T]) -> Iterator[Tuple[_T, ...]]:
def nunpack(s: bytes, default: int = 0) -> int:
def decode_text(s: bytes) -> str:
def enc(x: str) -> str:
def bbox2str(bbox: Rect) -> str:
def matrix2str(m: Matrix) -> str:
def vecBetweenBoxes(obj1: "LTComponent", obj2: "LTComponent") -> Point:
    def __init__(self, bbox: Rect, gridsize: int = 50) -> None:
    def __repr__(self) -> str:
    def __iter__(self) -> Iterator[LTComponentT]:
    def __len__(self) -> int:
    def __contains__(self, obj: object) -> bool:
    def _getrange(self, bbox: Rect) -> Iterator[Point]:
    def extend(self, objs: Iterable[LTComponentT]) -> None:
    def add(self, obj: LTComponentT) -> None:
    def remove(self, obj: LTComponentT) -> None:
    def find(self, bbox: Rect) -> Iterator[LTComponentT]:
def format_int_roman(value: int) -> str:
def format_int_alpha(value: int) -> str: INF = (1 << 31) - 1
MATRIX_IDENTITY: Matrix = (1, 0, 0, 1, 0, 0)
_T = TypeVar("_T")
ROMAN_ONES = ["i", "x", "c", "m"]
ROMAN_FIVES = ["v", "l", "d"]
class open_filename(object):
class Plane(Generic[LTComponentT]):
    def __init__(self, filename: FileOrName, *args: Any, **kwargs: Any) -> None:
    def __enter__(self) -> AnyIO:
    def __exit__(self, exc_type: object, exc_val: object, exc_tb: object) -> None:
def make_compat_bytes(in_str: str) -> bytes:
def make_compat_str(o: object) -> str:
def shorten_str(s: str, size: int) -> str:
def compatible_encode_method(
    bytesorstring: Union[bytes, str], encoding: str = "utf-8", erraction: str = "ignore"
) -> str:
def paeth_predictor(left: int, above: int, upper_left: int) -> int:
def apply_png_predictor(
    pred: int, colors: int, columns: int, bitspercomponent: int, data: bytes
) -> bytes:
def mult_matrix(m1: Matrix, m0: Matrix) -> Matrix:
def translate_matrix(m: Matrix, v: Point) -> Matrix:
def apply_matrix_pt(m: Matrix, v: Point) -> Point:
def apply_matrix_norm(m: Matrix, v: Point) -> Point:
def isnumber(x: object) -> bool:
def uniq(objs: Iterable[_T]) -> Iterator[_T]:
def fsplit(pred: Callable[[_T], bool], objs: Iterable[_T]) -> Tuple[List[_T], List[_T]]:
def drange(v0: float, v1: float, d: int) -> range:
def get_bound(pts: Iterable[Point]) -> Rect:
def pick(
    seq: Iterable[_T], func: Callable[[_T], float], maxobj: Optional[_T] = None
) -> Optional[_T]:
def choplist(n: int, seq: Iterable[_T]) -> Iterator[Tuple[_T, ...]]:
def nunpack(s: bytes, default: int = 0) -> int:
def decode_text(s: bytes) -> str:
def enc(x: str) -> str:
def bbox2str(bbox: Rect) -> str:
def matrix2str(m: Matrix) -> str:
def vecBetweenBoxes(obj1: "LTComponent", obj2: "LTComponent") -> Point:
    def __init__(self, bbox: Rect, gridsize: int = 50) -> None:
    def __repr__(self) -> str:
    def __iter__(self) -> Iterator[LTComponentT]:
    def __len__(self) -> int:
    def __contains__(self, obj: object) -> bool:
    def _getrange(self, bbox: Rect) -> Iterator[Point]:
    def extend(self, objs: Iterable[LTComponentT]) -> None:
    def add(self, obj: LTComponentT) -> None:
    def remove(self, obj: LTComponentT) -> None:
    def find(self, bbox: Rect) -> Iterator[LTComponentT]:
def format_int_roman(value: int) -> str:
def format_int_alpha(value: int) -> str: def apply_matrix_pt(m: Matrix, v: Point) -> Point:
    (a, b, c, d, e, f) = m
    (x, y) = v
    """Applies a matrix to a point."""
    return a * x + c * y + e, b * x + d * y + f def bbox2str(bbox: Rect) -> str:
    (x0, y0, x1, y1) = bbox
    return "{:.3f},{:.3f},{:.3f},{:.3f}".format(x0, y0, x1, y1) def fsplit(pred: Callable[[_T], bool], objs: Iterable[_T]) -> Tuple[List[_T], List[_T]]:
    """Split a list into two classes according to the predicate."""
    t = []
    f = []
    for obj in objs:
        if pred(obj):
            t.append(obj)
        else:
            f.append(obj)
    return t, f def get_bound(pts: Iterable[Point]) -> Rect:
    """Compute a minimal rectangle that covers all the points."""
    limit: Rect = (INF, INF, -INF, -INF)
    (x0, y0, x1, y1) = limit
    for (x, y) in pts:
        x0 = min(x0, x)
        y0 = min(y0, y)
        x1 = max(x1, x)
        y1 = max(y1, y)
    return x0, y0, x1, y1 def matrix2str(m: Matrix) -> str:
    (a, b, c, d, e, f) = m
    return "[{:.2f},{:.2f},{:.2f},{:.2f}, ({:.2f},{:.2f})]".format(a, b, c, d, e, f) def uniq(objs: Iterable[_T]) -> Iterator[_T]:
    """Eliminates duplicated elements."""
    done = set()
    for obj in objs:
        if obj in done:
            continue
        done.add(obj)
        yield obj
    return
import heapq
import logging
from typing import (
    Dict,
    Generic,
    Iterable,
    Iterator,
    List,
    Optional,
    Sequence,
    Set,
    Tuple,
    TypeVar,
    Union,
    cast,
)
from .pdfcolor import PDFColorSpace
from .pdffont import PDFFont
from .pdfinterp import Color
from .pdfinterp import PDFGraphicState
from .pdftypes import PDFStream
from .utils import INF
from .utils import LTComponentT
from .utils import Matrix
from .utils import Plane
from .utils import Point
from .utils import Rect
from .utils import apply_matrix_pt
from .utils import bbox2str
from .utils import fsplit
from .utils import get_bound
from .utils import matrix2str
from .utils import uniq
            return 0
        else:
            return min(abs(self.x0 - obj.x1), abs(self.x1 - obj.x0))

    def hoverlap(self, obj: "LTComponent") -> float:
        assert isinstance(obj, LTComponent), str(type(obj))
        if self.is_hoverlap(obj):
            return min(abs(self.x0 - obj.x1), abs(self.x1 - obj.x0))
        else:
            return 0

    def is_voverlap(self, obj: "LTComponent") -> bool:
        assert isinstance(obj, LTComponent), str(type(obj))
        return obj.y0 <= self.y1 and self.y0 <= obj.y1

    def vdistance(self, obj: "LTComponent") -> float:
        assert isinstance(obj, LTComponent), str(type(obj))
        if self.is_voverlap(obj):
            return 0
        else:
            return min(abs(self.y0 - obj.y1), abs(self.y1 - obj.y0))

    def voverlap(self, obj: "LTComponent") -> float:
        assert isinstance(obj, LTComponent), str(type(obj))
        if self.is_voverlap(obj):
            return min(abs(self.y0 - obj.y1), abs(self.y1 - obj.y0))
        else:
            return 0


class LTCurve(LTComponent):
    """A generic Bezier curve"""

    def __init__(
        self,
        linewidth: float,
        pts: List[Point],
        stroke: bool = False,
        fill: bool = False,
        evenodd: bool = False,
        stroking_color: Optional[Color] = None,
        non_stroking_color: Optional[Color] = None,
    ) -> None:
        LTComponent.__init__(self, get_bound(pts))
        self.pts = pts
        self.linewidth = linewidth
        self.stroke = stroke
        self.fill = fill
        self.evenodd = evenodd
        self.stroking_color = stroking_color
        self.non_stroking_color = non_stroking_color

    def get_pts(self) -> str:
        return ",".join("%.3f,%.3f" % p for p in self.pts)


class LTLine(LTCurve):
    """A single straight line.

    Could be used for separating text or figures.
    """

    def __init__(
        self,
        linewidth: float,
        p0: Point,
        p1: Point,
        stroke: bool = False,
        fill: bool = False,
        evenodd: bool = False,
        stroking_color: Optional[Color] = None,
        non_stroking_color: Optional[Color] = None,
    ) -> None:
        LTCurve.__init__(
            self,
            linewidth,
            [p0, p1],
            stroke,
            fill,
            evenodd,
            stroking_color,
            non_stroking_color,
        )


class LTRect(LTCurve):
    """A rectangle.

    Could be used for framing another pictures or figures.
    """

    def __init__(
        self,
        linewidth: float,
        bbox: Rect,
        stroke: bool = False,
        fill: bool = False,
        evenodd: bool = False,
        stroking_color: Optional[Color] = None,
        non_stroking_color: Optional[Color] = None,
    ) -> None:
        (x0, y0, x1, y1) = bbox
        LTCurve.__init__(
            self,
            linewidth,
            [(x0, y0), (x1, y0), (x1, y1), (x0, y1)],
            stroke,
            fill,
            evenodd,
            stroking_color,
            non_stroking_color,
        )


class LTImage(LTComponent):
    """An image object.

    Embedded images can be in JPEG, Bitmap or JBIG2.
    """


    def __init__(self, name: str, stream: PDFStream, bbox: Rect) -> None: