CosOptimizer.java 10.3 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.internal.pdftoolkit.core.cos;

import com.adobe.internal.pdftoolkit.core.cos.CosArray;
import com.adobe.internal.pdftoolkit.core.cos.CosContainer;
import com.adobe.internal.pdftoolkit.core.cos.CosDictionary;
import com.adobe.internal.pdftoolkit.core.cos.CosDocument;
import com.adobe.internal.pdftoolkit.core.cos.CosList;
import com.adobe.internal.pdftoolkit.core.cos.CosNumeric;
import com.adobe.internal.pdftoolkit.core.cos.CosObject;
import com.adobe.internal.pdftoolkit.core.cos.CosObjectInfo;
import com.adobe.internal.pdftoolkit.core.cos.CosStream;
import com.adobe.internal.pdftoolkit.core.cos.XRefTable;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFCosParseException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFIOException;
import com.adobe.internal.pdftoolkit.core.exceptions.PDFSecurityException;
import com.adobe.internal.pdftoolkit.core.types.ASName;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

final class CosOptimizer {
    CosOptimizer() {
    }

    static boolean freeUnreferencedObjects(CosDocument cosDoc, CosContainer[] roots, boolean fixStreamLengths) throws PDFCosParseException, PDFIOException, PDFSecurityException, IOException {
        CosList referencedInfos = CosOptimizer.findReferencedIndirectObjects(roots, fixStreamLengths);
        CosList objStmInfos = cosDoc.getObjStmInfos();
        Iterator iter = objStmInfos.iterator();
        while (iter.hasNext()) {
            CosObjectInfo stmInfo = (CosObjectInfo)iter.next();
            referencedInfos.add(stmInfo.getObjNum(), stmInfo);
        }
        CosList allInfos = cosDoc.buildObjectList(false);
        iter = allInfos.iterator();
        boolean objectsFreed = false;
        while (iter.hasNext()) {
            CosObjectInfo info = (CosObjectInfo)iter.next();
            if (referencedInfos.get(info.getObjNum()) != null) continue;
            CosObject obj = info.getObject(false);
            if (obj != null) {
                obj.close();
            }
            info.markFree();
            objectsFreed = true;
        }
        return objectsFreed;
    }

    static CosObject[] getUnreferencedObjects(CosDocument cosDoc, CosContainer[] roots) throws PDFCosParseException, PDFIOException, PDFSecurityException, IOException {
        CosList referencedInfos = CosOptimizer.findReferencedIndirectObjects(roots, false);
        CosList objStmInfos = cosDoc.getObjStmInfos();
        Iterator iter = objStmInfos.iterator();
        while (iter.hasNext()) {
            CosObjectInfo stmInfo = (CosObjectInfo)iter.next();
            referencedInfos.add(stmInfo.getObjNum(), stmInfo);
        }
        CosList allInfos = cosDoc.buildObjectList(false);
        CosList unrefedObjs = new CosList();
        iter = allInfos.iterator();
        while (iter.hasNext()) {
            CosObjectInfo info = (CosObjectInfo)iter.next();
            if (referencedInfos.get(info.getObjNum()) != null) continue;
            CosObject obj = info.getObject();
            if (obj == null) {
                obj = cosDoc.getXRef().getIndirectObject(info);
            }
            if (obj == null) continue;
            unrefedObjs.add(info.getObjNum(), obj);
        }
        if (unrefedObjs.isEmpty()) {
            return null;
        }
        CosObject[] list = new CosObject[unrefedObjs.count()];
        iter = unrefedObjs.iterator();
        int idx = 0;
        while (iter.hasNext()) {
            list[idx++] = (CosObject)iter.next();
        }
        return list;
    }

    private static CosList findReferencedIndirectObjects(CosContainer[] roots, boolean fixStreamLengths) throws PDFCosParseException, PDFIOException, PDFSecurityException {
        if (roots == null) {
            return null;
        }
        CosList foundObjects = new CosList();
        for (int i = 0; i < roots.length; ++i) {
            CosContainer root = roots[i];
            if (root == null) continue;
            if (root.isIndirect()) {
                foundObjects.add(root.getInfo().getObjNum(), root.getInfo());
            }
            CosOptimizer.findReferencedIndirectObjects(root, foundObjects, fixStreamLengths);
        }
        return foundObjects;
    }

    private static void findReferencedIndirectObjects(CosContainer container, CosList foundObjects, boolean fixStreamLengths) throws PDFCosParseException, PDFIOException, PDFSecurityException {
        ArrayList<Object> stateStack = new ArrayList<Object>();
        Iterator containerIter = null;
        CosObject containerItem = null;
        boolean pushState = true;
        do {
            if (pushState) {
                if (container instanceof CosArray) {
                    containerIter = ((CosArray)container).iterator();
                } else {
                    CosObject cosLength;
                    if (fixStreamLengths && container instanceof CosStream && (cosLength = ((CosStream)container).get(ASName.k_Length)) instanceof CosNumeric && cosLength.isIndirect()) {
                        cosLength = cosLength.getDocument().createCosNumeric(cosLength.numberValue());
                        ((CosStream)container).put(ASName.k_Length, cosLength);
                    }
                    List<ASName> keys = ((CosDictionary)container).getKeys();
                    containerIter = keys.iterator();
                }
                pushState = false;
            }
            while (containerIter.hasNext()) {
                if (container instanceof CosArray) {
                    containerItem = containerIter.next();
                } else {
                    ASName key = (ASName)((Object)containerIter.next());
                    containerItem = ((CosDictionary)container).get(key);
                }
                if (containerItem == null) continue;
                CosObjectInfo itemInfo = containerItem.getInfo();
                if (itemInfo != null) {
                    if (foundObjects.get(itemInfo.getObjNum()) != null) continue;
                    foundObjects.add(itemInfo.getObjNum(), itemInfo);
                }
                if (!(containerItem instanceof CosContainer)) continue;
                pushState = true;
                break;
            }
            if (pushState) {
                stateStack.add(container);
                stateStack.add(containerIter);
                container = (CosContainer)containerItem;
                continue;
            }
            if (stateStack.isEmpty()) {
                return;
            }
            containerIter = (Iterator)stateStack.get(stateStack.size() - 1);
            stateStack.remove(stateStack.size() - 1);
            container = (CosContainer)stateStack.get(stateStack.size() - 1);
            stateStack.remove(stateStack.size() - 1);
        } while (true);
    }

    static void freeUnreferencedObjectsIncremental(CosDocument cosDoc, int objNumLimit) throws PDFCosParseException, PDFIOException, PDFSecurityException, IOException {
        CosObjectInfo info;
        CosObjectInfo info2;
        CosList oldDirtyObjects = new CosList();
        CosList newDirtyObjects = cosDoc.buildObjectList(true);
        Iterator iter = newDirtyObjects.iterator();
        while (iter.hasNext() && (info2 = (CosObjectInfo)iter.next()).getObjNum() < objNumLimit) {
            oldDirtyObjects.add(info2.getObjNum(), info2);
            iter.remove();
        }
        CosList referencedDirtyObjects = new CosList();
        iter = oldDirtyObjects.iterator();
        while (iter.hasNext()) {
            info = (CosObjectInfo)iter.next();
            CosOptimizer.findReferencedIndirectObjectsIncremental(info.getObject(), referencedDirtyObjects);
        }
        CosOptimizer.findReferencedIndirectObjectsIncremental(cosDoc.getTrailer(), referencedDirtyObjects);
        iter = newDirtyObjects.iterator();
        while (iter.hasNext()) {
            info = (CosObjectInfo)iter.next();
            if (referencedDirtyObjects.get(info.getObjNum()) != null) continue;
            CosObject obj = info.getObject(false);
            if (obj != null) {
                obj.close();
            }
            info.markFree();
        }
    }

    private static void findReferencedIndirectObjectsIncremental(CosObject obj, CosList list) throws PDFCosParseException, PDFIOException, PDFSecurityException {
        if (!(obj instanceof CosContainer)) {
            return;
        }
        CosContainer container = (CosContainer)obj;
        ArrayList<Object> stateStack = new ArrayList<Object>();
        Iterator containerIter = null;
        CosObject containerItem = null;
        boolean pushState = true;
        do {
            if (pushState) {
                if (container instanceof CosArray) {
                    containerIter = ((CosArray)container).iterator();
                } else {
                    List<ASName> keys = ((CosDictionary)container).getKeys();
                    containerIter = keys.iterator();
                }
                pushState = false;
            }
            while (containerIter.hasNext()) {
                if (container instanceof CosArray) {
                    containerItem = containerIter.next();
                } else {
                    ASName key = (ASName)((Object)containerIter.next());
                    containerItem = ((CosDictionary)container).get(key);
                }
                if (containerItem == null) continue;
                CosObjectInfo itemInfo = containerItem.getInfo();
                if (itemInfo != null) {
                    if (!itemInfo.isDirty() || list.get(itemInfo.getObjNum()) != null) continue;
                    list.add(containerItem.getInfo().getObjNum(), containerItem.getInfo());
                }
                if (!(containerItem instanceof CosContainer)) continue;
                pushState = true;
                break;
            }
            if (pushState) {
                stateStack.add(container);
                stateStack.add(containerIter);
                container = (CosContainer)containerItem;
                continue;
            }
            if (stateStack.isEmpty()) {
                return;
            }
            containerIter = (Iterator)stateStack.get(stateStack.size() - 1);
            stateStack.remove(stateStack.size() - 1);
            container = (CosContainer)stateStack.get(stateStack.size() - 1);
            stateStack.remove(stateStack.size() - 1);
        } while (true);
    }
}