# SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved.
# Non-Commercial Freeware and Commercial Software.
# This class is generated using the converter UniSharping (www.unisharping.ru) from Pullenti C# project.
# The latest version of the code is available on the site www.pullenti.ru

import io
from pullenti.unisharp.Utils import Utils
from pullenti.unisharp.Streams import Stream

from pullenti.unitext.internal.pdf.PdfMiscInfo import PdfMiscInfo
from pullenti.unitext.internal.pdf.PdfName import PdfName
from pullenti.unitext.internal.pdf.PdfBoolValue import PdfBoolValue
from pullenti.unitext.internal.pdf.PdfRect import PdfRect
from pullenti.unitext.internal.pdf.PdfText import PdfText
from pullenti.unitext.internal.pdf.PdfArray import PdfArray
from pullenti.unitext.internal.pdf.IPdfDictionaryWrapper import IPdfDictionaryWrapper
from pullenti.unitext.internal.pdf.PdfImage import PdfImage
from pullenti.unitext.internal.pdf.PdfStream import PdfStream
from pullenti.unitext.internal.pdf.PdfPathState import PdfPathState
from pullenti.unitext.internal.pdf.Matrix import Matrix
from pullenti.unitext.internal.pdf.PdfFont import PdfFont
from pullenti.unitext.internal.pdf.PdfTextState import PdfTextState

class PdfPage(PdfRect, IPdfDictionaryWrapper):
    
    @property
    def dic(self) -> 'PdfDictionary':
        return self.__dic
    @dic.setter
    def dic(self, value) -> 'PdfDictionary':
        self.__dic = value
        return self.__dic
    
    def __init__(self, dic_ : 'PdfDictionary', state0 : object=None, store_lexems : bool=False, ignore_images : bool=False) -> None:
        super().__init__()
        self.__dic = None;
        self.lexems = None
        self.subpages = None
        self.lexem_content = None;
        self.items = list()
        self.imgs = list()
        self.begin_pos = 0
        self.end_pos = 0
        self.dic = dic_
        dic_.obj = (self)
        crop = Utils.asObjectOrNull(dic_.get_object("CropBox", False), PdfArray)
        if (crop is None): 
            crop = (Utils.asObjectOrNull(dic_.get_object("TrimBox", False), PdfArray))
        if (crop is None): 
            crop = (Utils.asObjectOrNull(dic_.get_object("MediaBox", False), PdfArray))
        if (crop is None): 
            crop = (Utils.asObjectOrNull(dic_.get_object("BBox", False), PdfArray))
        if (crop is None): 
            if (dic_.source_file.root_object is not None): 
                pages = dic_.source_file.root_object.get_dictionary("Pages", None)
                if (pages is not None): 
                    crop = (Utils.asObjectOrNull(pages.get_object("MediaBox", False), PdfArray))
                    if (crop is None): 
                        crop = (Utils.asObjectOrNull(pages.get_object("TrimBox", False), PdfArray))
                    if (crop is None): 
                        crop = (Utils.asObjectOrNull(pages.get_object("CropBox", False), PdfArray))
        if (crop is not None and crop.items_count == 4): 
            self.x2 = crop.get_item(2, False).get_double()
            self.y2 = crop.get_item(3, False).get_double()
            rot = dic_.get_object("Rotate", False)
            if (rot is not None and ((rot.get_double() == 90 or rot.get_double() == 270))): 
                xx = self.x2
                self.x2 = self.y2
                self.y2 = xx
        res = self.dic.get_dictionary("Resources", None)
        fnts = (None if res is None else res.get_dictionary("Font", None))
        imgs_ = (None if res is None else res.get_dictionary("XObject", None))
        val = self.dic.get_total_data_stream("Contents")
        if (val is None and ((state0 is not None or self.dic.is_type_item("XObject")))): 
            val = self.dic.extract_data()
        if (val is None or (len(val) < 1)): 
            return
        lex = None
        with PdfStream(None, val) as pstr: 
            lex = pstr.parse_content()
        if (store_lexems): 
            self.lexems = lex
            self.lexem_content = val
        all_fonts = dict()
        state = Utils.asObjectOrNull(state0, PdfTextState)
        if (state is None): 
            state = PdfTextState()
            state.box_height = self.y2
        else: 
            mat = Utils.asObjectOrNull(dic_.get_object("Matrix", False), PdfArray)
            if (mat is not None and mat.items_count == 6): 
                m = Matrix()
                m.set0_(mat.get_item(0, False).get_double(), mat.get_item(1, False).get_double(), mat.get_item(2, False).get_double(), mat.get_item(3, False).get_double(), mat.get_item(4, False).get_double(), mat.get_item(5, False).get_double())
                if (len(state.ctm_stack) > 0): 
                    m.multiply(state.ctm_stack[0])
                    state.ctm_stack[0] = m
        text_regime = False
        buf = io.StringIO()
        path = PdfPathState(self)
        i = 0
        first_pass717 = True
        while True:
            if first_pass717: first_pass717 = False
            else: i += 1
            if (not (i < len(lex))): break
            if (not (isinstance(lex[i], PdfName))): 
                continue
            nam = lex[i].name
            if (nam == "ET"): 
                text_regime = False
                continue
            if (nam == "BT"): 
                text_regime = True
                state.tm.init()
                state.tlm.init()
                continue
            if (nam == "Do" and (isinstance(lex[i - 1], PdfName))): 
                nam = lex[i - 1].name
                xobjs = (None if res is None else res.get_dictionary("XObject", None))
                xobj = (None if xobjs is None else xobjs.get_dictionary(nam, None))
                if (xobj is None): 
                    for rr in dic_.source_file.all_resources: 
                        if (rr.get_string_item("Name") == nam): 
                            xobj = rr
                            break
                if (xobj is not None): 
                    sub = Utils.asObjectOrNull(xobj.get_object("Subtype", False), PdfName)
                    if (sub is not None and sub.name == "Image"): 
                        lex[i].tag = (xobj)
                        self.imgs.append(PdfMiscInfo._new232(xobj, lex[i - 1].read_pos, ((lex[i].read_pos) + lex[i].read_len) - 1, nam))
                        im = Utils.asObjectOrNull(xobj.get_object("ImageMask", False), PdfBoolValue)
                        if (im is not None and im.val): 
                            pass
                        else: 
                            img = PdfImage(xobj, False, (None if state is None else state.fill_color), ignore_images)
                            lex[i].tag = (img)
                            if (len(state.ctm_stack) > 0): 
                                img.x2 = state.ctm_stack[0].e0_
                                img.x1 = img.x2
                                img.x2 += state.ctm_stack[0].a
                                img.y2 = state.box_height - state.ctm_stack[0].f
                                img.y1 = img.y2
                                img.y1 -= state.ctm_stack[0].d
                                if (((img.y1 < -0.1) or img.y2 > self.y2 or (img.x1 < -0.1)) or img.x2 > self.x2): 
                                    pass
                            self.items.append(img)
                            if (store_lexems): 
                                self.imgs[len(self.imgs) - 1].tag = (img)
                    else: 
                        ppp = PdfPage(xobj, state, store_lexems, ignore_images)
                        if (len(ppp.items) == 1 and (isinstance(ppp.items[0], PdfImage))): 
                            img = Utils.asObjectOrNull(ppp.items[0], PdfImage)
                            lex[i].tag = (img)
                            self.items.append(img)
                            if (store_lexems and len(ppp.imgs) == 1): 
                                self.imgs.append(ppp.imgs[0])
                                self.imgs[len(self.imgs) - 1].tag = (img)
                        else: 
                            self.items.extend(ppp.items)
                            if (self.subpages is None): 
                                self.subpages = list()
                            self.subpages.append(ppp)
                            lex[i].tag = (ppp)
                continue
            if (state.parse_one(lex, i)): 
                continue
            if (path.parse_one(lex, i)): 
                continue
            if (nam == "Tf" and (isinstance(lex[i - 2], PdfName))): 
                state.font_size = lex[i - 1].get_double()
                fnam = lex[i - 2].name
                if (not fnam in all_fonts): 
                    fff = None
                    if (fnts is not None): 
                        fff = fnts.get_dictionary(fnam, None)
                    if (fff is not None): 
                        if (isinstance(fff.obj, PdfFont)): 
                            state.font = (Utils.asObjectOrNull(fff.obj, PdfFont))
                        else: 
                            state.font = PdfFont(fff)
                            state.font.alias = fnam
                        fff.obj = (state.font)
                        all_fonts[fnam] = state.font
                else: 
                    state.font = all_fonts[fnam]
                continue
            if (text_regime and (((nam == "Tj" or nam == "TJ" or nam == "\"") or nam == "'"))): 
                if (state.font is None): 
                    continue
                if (nam == "\""): 
                    state.char_space = lex[i - 2].get_double()
                    state.word_space = lex[i - 3].get_double()
                if (nam == "\"" or nam == "'"): 
                    state.newline()
                txt = state.font._extract_text(lex[i - 1], state)
                if (txt is not None): 
                    self.items.append(txt)
                    lex[i].tag = (txt)
                continue
        if (self.y2 > 0): 
            for it in self.items: 
                k = 0
                while (k < 1000) and it.y1 > self.y2: 
                    it.y1 -= self.y2
                    it.y2 -= self.y2
                    k += 1
        if (not store_lexems): 
            i = 0
            while i < (len(self.items) - 1): 
                if ((isinstance(self.items[i], PdfText)) and (isinstance(self.items[i + 1], PdfText))): 
                    if (self.items[i].can_be_merged_with(Utils.asObjectOrNull(self.items[i + 1], PdfText))): 
                        self.items[i].merge_with(Utils.asObjectOrNull(self.items[i + 1], PdfText))
                        del self.items[i + 1]
                        i -= 1
                i += 1
        maxx = 0
        for it in self.items: 
            if (it.right > maxx): 
                maxx = it.right
        if (maxx > self.x2): 
            ratio = ((self.x2 - (3))) / maxx
            for it in self.items: 
                it.x1 *= ratio
                it.x2 *= ratio
    
    def get_data_content(self) -> bytearray:
        val = self.dic.get_total_data_stream("Contents")
        if (val is None): 
            val = self.dic.extract_data()
        if (val is None or (len(val) < 1)): 
            return None
        return val
    
    def clear_data_contents(self) -> None:
        self.dic.clear_total_data_stream("Contents")
        self.dic.set_data(None)
    
    def close(self) -> None:
        self.items.clear()
        self.imgs.clear()
        if (self.lexems is not None): 
            self.lexems.clear()
            self.lexems = (None)
        if (self.subpages is not None): 
            for sp in self.subpages: 
                sp.close()
            self.subpages.clear()
            self.subpages = (None)
    def __enter__(self): return self
    def __exit__(self, typ, val, traceback): self.close()