示例#1
0
bool YaffsControl::readImage() {
    int result = 0;
    memset(&mReadInfo, 0, sizeof(YaffsReadInfo));
    if (mImageFile) {
        while (result == 0) {
            result = readPage();
            if (result == -1) {
                if (feof(mImageFile)) {
                    mReadInfo.eofHasIncompletePage = true;
                    result = 1;
                }
                break;
            }
            processPage();
        }
    }
    mReadInfo.result = (result == 1);
    mObserver->readComplete();
    return mReadInfo.result;
}
示例#2
0
int
copyPdfFile(
    soPdfFile* inFile,
    soPdfFile* outFile
    )
{
    fz_error    *error;
    int         pageTreeNum, pageTreeGen;

    assert(inFile != NULL);
    assert(outFile != NULL);

    //
    // Process every page in the source file
    //
    {
        printf("\nProcessing input page : ");
        for (int pageNo = 0; pageNo < pdf_getpagecount(inFile->pageTree); pageNo++)
        {
            displayPageNumber(pageNo + 1, !pageNo);

            // Get the page object from the source
            fz_obj  *pageRef = inFile->pageTree->pref[pageNo];
            fz_obj  *pageObj = pdf_getpageobject(inFile->pageTree, pageNo);

            //
            // Process the page. Each page can be split into up-to 3 pages
            //
            fz_rect    bbRect[3];
            error = processPage(inFile, pageNo, bbRect, 3);
            if (error)
                return soPdfError(error);


            for (int ctr = 0; ctr < 3; ctr++)
            {
                // Check if this was a blank page
                if (fz_isemptyrect(bbRect[ctr]))
                    break;

                //
                // copy the source page dictionary entry. The way this is done is basically
                // by making a copy of the page dict object in the source file, and adding
                // the copy in the source file. Then the copied page dict object is 
                // referenced and added to the destination file.
                //
                // This convoluted procedure is done because the copy is done by pdf_transplant
                // function that accepts a source and destination. Whatever is referenced by
                // destination object is deep copied
                //
                

                // allocate an object id and generation id in source file
                //
                // There is a bug in mupdf where the object allocation returns
                // 0 oid and 0 gid when the input pdf file has iref stream
                // so to work around the issue, we wrap the pdf_allocojbect
                // in a for loop 10 times to get the number
                //
                int sNum, sGen, tries;

                for (tries = 0; tries < 10; tries++)
                {
                    error = pdf_allocobject(inFile->xref, &sNum, &sGen);
                    if (error)
                        return soPdfError(error);

                    // If sNum is non zero then the allocation was successful
                    if (sNum != 0)
                        break;  
                    pdf_updateobject(inFile->xref, sNum, sGen, pageObj);
                }

                // If we didn't succeed even after 10 tries then this file 
                // is not going to work.
                if (tries >= 10)
                    return soPdfError(fz_throw("cannot allocate object because of mupdf bug"));

                // make a deep copy of the original page dict
                fz_obj  *pageObj2;
                error = fz_deepcopydict(&pageObj2, pageObj);
                if (error)
                    return soPdfError(error);

                // update the source file with the duplicate page object
                pdf_updateobject(inFile->xref, sNum, sGen, pageObj2);

                fz_dropobj(pageObj2);

                // create an indirect reference to the page object
                fz_obj  *pageRef2;
                error = fz_newindirect(&pageRef2, sNum, sGen);
                if (error)
                    return soPdfError(error);

                // delete the parent dictionary entry
                // Do we need to delete any other dictionary entry 
                // like annot, tabs, metadata, etc
                fz_dictdels(pageObj2, "Parent");

                // Set the media box
                setPageMediaBox(inFile->xref, pageObj2, bbRect[ctr]);

                // Set the rotation based on input
                switch(p_mode)
                {
                    // no rotation if fit height
                case FitHeight:
                case Fit2xHeight:
                    break;

                    // rotate -90 deg if fit width
                case Fit2xWidth:
                case FitWidth:
                    setPageRotate(pageObj2, p_reverseLandscape ? 90 : -90);
                    break;

                case SmartFitHeight:
                case SmartFitWidth:
                default:
                    return soPdfError(fz_throw("Mode(%d) not yet implemented.", p_mode));
                    break;
                }


                // push the indirect reference to the destination list for copy by pdf_transplant
                error = fz_arraypush(outFile->editobjs, pageRef2);
                if (error)
                    return soPdfError(error);
            }
        }
    }

    // flush the objects into destination from source
    {
        fz_obj      *results;
        int         outPages;

        printf("\nCopying output page : ");
        error = pdf_transplant(outFile->xref, inFile->xref, &results, outFile->editobjs);
        if (error)
            return soPdfError(error);

        outPages = fz_arraylen(results);
        for (int ctr = 0; ctr < outPages; ctr++)
        {
            displayPageNumber(ctr + 1, !ctr);
            error = fz_arraypush(outFile->pagelist, fz_arrayget(results, 
                p_reverseLandscape ? outPages - 1 - ctr : ctr));
            if (error)
                return soPdfError(error);
        }

        fz_dropobj(results);
    }

    // flush page tree

    // Create page tree and add back-links
    {
        fz_obj  *pageTreeObj;
        fz_obj  *pageTreeRef;

        // allocate a new object in out file for pageTree object
        error = pdf_allocobject(outFile->xref, &pageTreeNum, &pageTreeGen);
        if (error)
            return soPdfError(error);

        // Create a page tree object
        error = fz_packobj(&pageTreeObj, "<</Type/Pages/Count %i/Kids %o>>",
            fz_arraylen(outFile->pagelist), outFile->pagelist);
        if (error)
            return soPdfError(error);

        // Update the xref entry with the pageTree object
        pdf_updateobject(outFile->xref, pageTreeNum, pageTreeGen, pageTreeObj);

        fz_dropobj(pageTreeObj);

        // Create a reference to the pageTree object
        error = fz_newindirect(&pageTreeRef, pageTreeNum, pageTreeGen);
        if (error)
            return soPdfError(error);

        //
        // For every page in the output file, update the parent entry
        //
        for (int ctr = 0; ctr < fz_arraylen(outFile->pagelist); ctr++)
        {
            fz_obj  *pageObj;

            int num = fz_tonum(fz_arrayget(outFile->pagelist, ctr));
            int gen = fz_togen(fz_arrayget(outFile->pagelist, ctr));

            // Get the page object from xreft
            error = pdf_loadobject(&pageObj, outFile->xref, num, gen);
            if (error)
                return soPdfError(error);

            // Update the parent entry in the page dictionary
            error = fz_dictputs(pageObj, "Parent", pageTreeRef);
            if (error)
                return soPdfError(error);

            // Update the entry with the updated page object
            pdf_updateobject(outFile->xref, num, gen, pageObj);

            fz_dropobj(pageObj);
        }
    }

    // Create catalog and root entries
    {
        fz_obj  *catObj, *infoObj;
        int     rootNum, rootGen;
        int     infoNum, infoGen;

        //
        // Copy the info catalog to the destination

        // alloc an object id and gen id in destination file
        error = pdf_allocobject(outFile->xref, &infoNum, &infoGen);
        if (error)
            return soPdfError(error);

        // make a deep copy of the original page dict
        error = fz_deepcopydict(&infoObj, inFile->xref->info);
        if (error)
            return soPdfError(error);

        // update the dest file with object
        pdf_updateobject(outFile->xref, infoNum, infoGen, infoObj);
        outFile->xref->info = infoObj;

        fz_dropobj(infoObj);

        //
        // root/catalog object creation
        error = pdf_allocobject(outFile->xref, &rootNum, &rootGen);
        if (error)
            return soPdfError(error);

        error = fz_packobj(&catObj, "<</Type/Catalog /Pages %r>>", pageTreeNum, pageTreeGen);
        if (error)
            return soPdfError(error);

        pdf_updateobject(outFile->xref, rootNum, rootGen, catObj);

        fz_dropobj(catObj);

        // Create trailer
        error = fz_packobj(&outFile->xref->trailer, "<</Root %r /Info %r>>", 
            rootNum, rootGen, infoNum, infoGen);
        if (error)
            return soPdfError(error);

    }

    // Update the info in the target file and save the xref
    printf("\nSaving.\n");
    error = setPageInfo(inFile, outFile);
    if (error)
        return soPdfError(error);

    error = pdf_savexref(outFile->xref, outFile->fileName, NULL);
    if (error)
        return soPdfError(error);

    if (g_errorCount != 0)
    {
        printf("\nFollowing issues encounted were ignored.\n\n");
        for (int ctr = g_errorCount - 1; ctr >= 0; ctr--)
            soPdfError(g_errorList[ctr]);
    }
    printf("\nSaved.\n");

    return 0;
}
bool PdfBookReader::readBook(shared_ptr<ZLInputStream> stream) {
	if (stream.isNull() || !stream->open()) {
		return false;
	}

	readLine(*stream, myBuffer);
	if (!ZLStringUtil::stringStartsWith(myBuffer, "%PDF-")) {
		return false;
	}

	std::string version = myBuffer.substr(5);
	std::cerr << "version = " << version << "\n";

	size_t eofOffset = stream->sizeOfOpened();
	if (eofOffset < 100) {
		return false;
	}

	stream->seek(eofOffset - 100, true);
	bool readXrefOffset = false;
	size_t xrefOffset = (size_t)-1;
	while (true) {
		readLine(*stream, myBuffer);
		if (myBuffer.empty()) {
			break;
		}
		stripBuffer(myBuffer);
		if (readXrefOffset) {
			if (!myBuffer.empty()) {
				xrefOffset = atoi(myBuffer.c_str());
				break;
			}
		} else if (myBuffer == "startxref") {
			readXrefOffset = true;
		}
	}

	if (!readReferenceTable(*stream, xrefOffset)) {
		return false;
	}

	PdfDictionaryObject &trailerDictionary = (PdfDictionaryObject&)*myTrailer;
	shared_ptr<PdfObject> root = resolveReference(trailerDictionary["Root"], *stream);
	if (root.isNull() || (root->type() != PdfObject::DICTIONARY)) {
		return false;
	}

	PdfDictionaryObject &rootDictionary = (PdfDictionaryObject&)*root;
	if (rootDictionary["Type"] != PdfNameObject::nameObject("Catalog")) {
		return false;
	}
	shared_ptr<PdfObject> pageRootNode = resolveReference(rootDictionary["Pages"], *stream);
	if (pageRootNode.isNull() || (pageRootNode->type() != PdfObject::DICTIONARY)) {
		return false;
	}
	PdfDictionaryObject &pageRootNodeDictionary = (PdfDictionaryObject&)*pageRootNode;
	if (pageRootNodeDictionary["Type"] != PdfNameObject::nameObject("Pages")) {
		return false;
	}
	
	/*
	shared_ptr<PdfObject> count = pageRootNodeDictionary["Count"];
	if (!count.isNull() && (count->type() == PdfObject::INTEGER_NUMBER)) {
		std::cerr << "count = " << ((PdfIntegerObject&)*count).value() << "\n";
	}
	*/
	shared_ptr<PdfObject> pages = pageRootNodeDictionary["Kids"];
	if (pages.isNull() || (pages->type() != PdfObject::ARRAY)) {
		return false;
	}
	const PdfArrayObject& pagesArray = (const PdfArrayObject&)*pages;
	const size_t pageNumber = pagesArray.size();
	for (size_t i = 0; i < pageNumber; ++i) {
		processPage(pagesArray[i], *stream);
	}

	return true;
}
示例#4
0
bool OggPacketiser::acceptOggPage(OggPage* inOggPage) {				//AOP::: Needs closer look
	auto_ptr<OggPage> op(inOggPage);
	//All callers to acceptOggPage give away their pointer
	// to this function. All functions implementing this interface
	// are responsible for deleting this page. All callers
	// should NULL their pointer immediately after calling
	// to avoid reusing them.
	// 

	//debugLog<<"acceptOggPage : Gran = "<<inOggPage->header()->GranulePos()<<"Num packs = "<<inOggPage->numPackets()<<endl;

	//If the page isn't a -1 page and it's got a different granpos save it.
	//if ( (inOggPage->header()->GranulePos() != -1) && (inOggPage->header()->GranulePos() != mCurrentGranPos)) {
	//	mPrevGranPos = mCurrentGranPos;

	//	//If the previous is higher than the
	//	if (mPrevGranPos > mCurrentGranPos) {
	//		mPrevGranPos = -1;
	//	}
	//	mCurrentGranPos = inOggPage->header()->GranulePos();
	//}

	//If the page header says its a continuation page...
	if ((inOggPage->header()->HeaderFlags() & 1) == 1) {
		//debugLog<<"acceptOggPage : Page says cont..."<<endl;
		
		///... and there is at least 1 packet...
		if (inOggPage->numPackets() > 0) {
			//debugLog<<"acceptOggPage : ...and there is at least 1 packet..."<<endl;
		
			//... and we were expecting a continuation...
			if (mPacketiserState == PKRSTATE_AWAITING_CONTINUATION) {
				//debugLog<<"acceptOggPage : ... and we were waiting for a cont..."<<endl;

				//... and the first packet is marked as a continuation...
				if (inOggPage->getStampedPacket(0)->isContinuation()) {
					//debugLog<<"acceptOggPage : ... and the first packet is a cont..."<<endl;

					//... merge this packet into our pending page.
					//ASSERT when mPacketiserState = PKRSTATE_AWAITING_CONTINUATION, mPending page != NULL
					mPendingPacket->merge(inOggPage->getStampedPacket(0));
					
					//If even after merging this packet is still truncated...
					if (mPendingPacket->isTruncated()) {
						//debugLog<<"acceptOggPage : ... but the pending packet is still truncated..."<<endl;
						//Packet still not full. special case full page.
						//===
						// The only way the the pending packet can be truncated is if
						//  the first packet in the page is truncated, and the first
						//  packet in a page can only be truncated if it's also the 
						//  only packet on the page.
						//Considering it is incomplete ending a page the granule pos
						// will be -1.
						//This is a special type of page :
						// 1 incomlpete packet on the page
						// Continuation flag set
						// No complete packets end on this page
						// Granule pos is -1

						//debugLog<<"acceptOggPage : Go to cont state."<<endl;
						//We are still waiting for another continuation...
						mPacketiserState = PKRSTATE_AWAITING_CONTINUATION;		//This should be redundant, we should already be in this state.
						//First packet on page is now merged into pending packet.
					} else {
						//debugLog<<"acceptOggPage : ... now we can deliver it..."<<endl;
						//... the pending packet is now complete.
						
						//TODO::: Static alternative here ?
						
						//Deliver the packet to the packet sink...
						if (dispatchStampedOggPacket(mPendingPacket) == false) {
							//debugLog<<"acceptOggPage : DELIVERY FAILED !"<<endl;
							mPacketiserState = PKRSTATE_OK;
							mPendingPacket = NULL;
							//delete inOggPage;
							//inOggPage = 0;
							return false;
						}
						//debugLog<<"acceptOggPage : ... delivery sucessful..."<<endl;
						//debugLog<<"acceptOggPage : Back to OK State..."<<endl;
						//Go back to OK state
						mPacketiserState = PKRSTATE_OK;
						mPendingPacket = NULL;
						//First packet on page is merged and delivered.
					}
					//debugLog<<"acceptOggPage : Send all the other packets besides first and last..."<<endl;
					//Send every packet except the first and last to the packet sink.
					processPage(inOggPage, false, false);
				} else {
					//debugLog<<"acceptOggPage : INTERNAL ERROR - Header says cont but packet doesn't."<<endl;
					//Header flag says continuation but first packet is not continued.
					mPacketiserState = PKRSTATE_INVALID_STREAM;
					
					//delete inOggPage;
					//inOggPage = 0;
					throw 0;
				}
			} else {
				//debugLog<<"acceptOggPage : UNEXPECTED CONT !"<<endl;
				if (mLooseMode == true) {
					//debugLog<<"acceptOggPage : ... but we are ignoring it !"<<endl;
					//Just ignore when we get continuation pages, just drop the broken bit of packet.
					if( mPendingPacket ) { delete mPendingPacket; mPendingPacket = NULL; }
					mPendingPacket = NULL;   //MEMCHECK::: Did i just leak memory ?
					mPacketiserState = PKRSTATE_OK;

					//TODO::: Should really return false here if this returns false.
					if( processPage(inOggPage, false, false) == false) {
						//TODO::: State change ???
						//delete inOggPage;
						//inOggPage = 0;
						return false;
					}
				} else {
					//debugLog<<"acceptOggPage : FAILURE !!!!"<<endl;
					//Unexpected continuation
					mPacketiserState = PKRSTATE_INVALID_STREAM;
					throw 0;
				}
			}
		} else {
			//debugLog<<"acceptOggPage : UNKNOWN CASE"<<endl;
			//Is this something ?
			//UNKNOWN CASE::: Header continuation flag set, but no packets on page.
			mPacketiserState = PKRSTATE_INVALID_STREAM;
			//delete inOggPage;
			//inOggPage = 0;
			throw 0;
		}
	} else {
		//debugLog<<"acceptOggPage : We have a normal page... dumping all but the last..."<<endl;
		//Normal page, no continuations... just dump the packets, except the last one
		if (inOggPage->numPackets() == 1) {

			//I think the bug is here... by sending a trunc packet and not updating state.

			//debugLog<<"acceptOggPage : Only one packet on this normal page..."<<endl;

			if (inOggPage->getPacket(0)->isTruncated()) {
				//debugLog<<"acceptOggPage : ...and it's truncated... so we save it."<<endl;
				//ASSERT : mPending packet is NULL, because this is not a continuation page.
				if( mPendingPacket ) { delete mPendingPacket; mPendingPacket = NULL; }
				mPendingPacket = (StampedOggPacket*)inOggPage->getStampedPacket(0)->clone();
				//debugLog<<"acceptOggPage : Moving to CONT state."<<endl;
				mPacketiserState = PKRSTATE_AWAITING_CONTINUATION;

			} else {
				//debugLog<<"acceptOggPage : Only one packet on this normal page..."<<endl;
				if (processPage(inOggPage, true, true) == false ) {			//If there was only one pack process it.
					//debugLog<<"acceptOggPage : FAIL STATE DELIVERY"<<endl;
					//TODO::: State change
					//delete inOggPage;
					//inOggPage = 0;
					return false;
				}

				//We should never go into the if below now as the packet is taken care of.
			}
		} else {
			//debugLog<<"acceptOggPage : More than one packet so dumping all but last..."<<endl;
			if (processPage(inOggPage, true, false) == false ) {			//If there was only one packet, no packets would be written
				//debugLog<<"acceptOggPage : FAIL STATE DELIVERY"<<endl;
				//TODO::: State change
				//delete inOggPage;
				//inOggPage = 0;
				return false;			
			}
		}
		
		//The first packet is delivered.
	}

	//debugLog<<"acceptOggPage : First pack should be delivered..."<<endl;
	//ASSERT: By this point something has been done with the first packet.

	// It was either merged with pending page and possibly delivered
	// or it was delivered by process page.
	//Code following assumes the first packet is dealt with already.
	
	//Now we deal with the last packet...
	//ASSERT : The last packet has only been sent if there was 1 or less packets.

	//If there is at least two packet on the page... ie at least one more packet we haven't processed.
	if (inOggPage->numPackets() > 1) {
		//debugLog<<"acceptOggPage : There is at least one packet on the page we haven't processed"<<endl;
		//... and we are in the OK state
		if (mPacketiserState == PKRSTATE_OK) {
			//debugLog<<"acceptOggPage : ... and we are in the OK state..."<<endl;
			//If the last packet is truncated.
			if (inOggPage->getPacket(inOggPage->numPackets() - 1)->isTruncated()) {
				//debugLog<<"acceptOggPage : ... but the last packet is trunced... so we save it and wait for cont..."<<endl;
				//The last packet is truncated. Save it and await continuation.
				
				//debugLog<<"acceptOggPage : Moving to CONT state..."<<endl;
				mPacketiserState = PKRSTATE_AWAITING_CONTINUATION;
			
				//ASSERT when mPacketiserState = OK, mPendingPacket = NULL
				if( mPendingPacket ) { delete mPendingPacket; mPendingPacket = NULL; }
				mPendingPacket = (StampedOggPacket*)(inOggPage->getStampedPacket(inOggPage->numPackets() - 1)->clone());
				//This packet is not delivered, it waits for a continuation.
			} else {
				//We are in the OK state, with no pending packets, and the last packet is not truncated.
				//debugLog<<"acceptOggPage : The last page is not trunc so we send it..."<<endl;
				//Deliver to the packet sink.
				if ( dispatchStampedOggPacket( (StampedOggPacket*)(inOggPage->getStampedPacket(inOggPage->numPackets() - 1)->clone()) ) == false ) {
					//debugLog<<"acceptOggPage : Delivery failed..."<<endl;
					//TODO::: State change ?
					//delete inOggPage;
					//inOggPage = 0;
					return false;
				}
				//The last packet is complete. So send it.
			}
		} else if (mPacketiserState == PKRSTATE_AWAITING_CONTINUATION) {
			//FIX::: This case should never occur.
			//debugLog<<"acceptOggPage : NEVER BE HERE 1"<<endl;
			
			//Packetiser state is not ok... what to do abo8ut it.
			
			//See special page case above.
			//This can only happen when we went through the special case above, and kept
			// the state in  the continuation state. But by definition it is impossible
			// for a subsequent packet on this page to be a continuation packet
			// as continuation packets can only be the first packet on the page.
			//This is more likely to be due to inconsistency of state code than invalidaity
			// of file.
			mPacketiserState = PKRSTATE_INVALID_STREAM;
			//delete inOggPage;
			//inOggPage = 0;
			throw 0;
		} else {
			//debugLog<<"acceptOggPage : NEVER BE HERE 2"<<endl;
			//Shouldn't be here
			mPacketiserState = PKRSTATE_INVALID_STREAM;
			//delete inOggPage;
			//inOggPage = 0;
			throw 0;
		}
	} else {
		//debugLog<<"acceptOggPage : 1 packet on page only, and we've taken care of it."<<endl;
		//Zero packets on page.
	}
	//debugLog<<"acceptOggPage : All ok... returning..."<<endl<<endl;
	//delete inOggPage;
	//inOggPage = 0;
	return true;
}