コード例 #1
0
EStatusCode CFFEmbeddedFontWriter::WriteEmbeddedFont(
	FreeTypeFaceWrapper& inFontInfo,
	const UIntVector& inSubsetGlyphIDs,
	const std::string& inFontFile3SubType,
	const std::string& inSubsetFontName,
	ObjectsContext* inObjectsContext,
	UShortVector* inCIDMapping,
	ObjectIDType& outEmbeddedFontObjectID)
{
	MyStringBuf rawFontProgram; 
	bool notEmbedded;
		// as oppose to true type, the reason for using a memory stream here is mainly peformance - i don't want to start
		// setting file pointers and move in a file stream
	EStatusCode status;

	do
	{
		status = CreateCFFSubset(inFontInfo,inSubsetGlyphIDs,inCIDMapping,inSubsetFontName,notEmbedded,rawFontProgram);
		if(status != PDFHummus::eSuccess)
		{
			TRACE_LOG("CFFEmbeddedFontWriter::WriteEmbeddedFont, failed to write embedded font program");
			break;
		}	

		if(notEmbedded)
		{
			// can't embed. mark succesful, and go back empty
			outEmbeddedFontObjectID = 0;
			TRACE_LOG("CFFEmbeddedFontWriter::WriteEmbeddedFont, font may not be embedded. so not embedding");
			return PDFHummus::eSuccess;
		}

		outEmbeddedFontObjectID = inObjectsContext->StartNewIndirectObject();
		
		DictionaryContext* fontProgramDictionaryContext = inObjectsContext->StartDictionary();

		rawFontProgram.pubseekoff(0,std::ios_base::beg);

		fontProgramDictionaryContext->WriteKey(scSubtype);
		fontProgramDictionaryContext->WriteNameValue(inFontFile3SubType);
		PDFStream* pdfStream = inObjectsContext->StartPDFStream(fontProgramDictionaryContext);


		// now copy the created font program to the output stream
		InputStringBufferStream fontProgramStream(&rawFontProgram);
		OutputStreamTraits streamCopier(pdfStream->GetWriteStream());
		status = streamCopier.CopyToOutputStream(&fontProgramStream);
		if(status != PDFHummus::eSuccess)
		{
			TRACE_LOG("CFFEmbeddedFontWriter::WriteEmbeddedFont, failed to copy font program into pdf stream");
			break;
		}


		inObjectsContext->EndPDFStream(pdfStream);
		delete pdfStream;
	}while(false);

	return status;	
}
コード例 #2
0
void DescendentFontWriter::WriteCIDSet(const UIntAndGlyphEncodingInfoVector& inEncodedGlyphs)
{
	mObjectsContext->StartNewIndirectObject(mCIDSetObjectID);
	PDFStream* pdfStream = mObjectsContext->StartPDFStream();	
	IByteWriter* cidSetWritingContext = pdfStream->GetWriteStream();
	Byte buffer;
	UIntAndGlyphEncodingInfoVector::const_iterator it = inEncodedGlyphs.begin();
	unsigned int upperLimit = inEncodedGlyphs.back().first;
	
	for(unsigned int i=0; i < upperLimit; i+=8)
	{
		buffer = (it->first == i) ? 1:0;
		if(it->first == i)
			++it;
		for(unsigned int j=1;j<8;++j)
		{
			buffer = buffer << 1;
			if(it != inEncodedGlyphs.end() && (it->first == i + j))
			{
				buffer |= 1;
				++it;
				if(it == inEncodedGlyphs.end())
					break;
			}
		}
		cidSetWritingContext->Write(&buffer,1);
	}
	mObjectsContext->EndPDFStream(pdfStream);
	delete pdfStream;
}
コード例 #3
0
EStatusCode TrueTypeEmbeddedFontWriter::WriteEmbeddedFont(	
								FreeTypeFaceWrapper& inFontInfo,
								const UIntVector& inSubsetGlyphIDs,
								ObjectsContext* inObjectsContext,
								ObjectIDType& outEmbeddedFontObjectID)
{
	MyStringBuf rawFontProgram;
	bool notEmbedded;
	EStatusCode status;

	do
	{
		status = CreateTrueTypeSubset(inFontInfo,inSubsetGlyphIDs,notEmbedded,rawFontProgram);
		if(status != PDFHummus::eSuccess)
		{
			TRACE_LOG("TrueTypeEmbeddedFontWriter::WriteEmbeddedFont, failed to write embedded font program");
			break;
		}	

		if(notEmbedded)
		{
			// can't embed. mark succesful, and go back empty
			outEmbeddedFontObjectID = 0;
			TRACE_LOG("TrueTypeEmbeddedFontWriter::WriteEmbeddedFont, font may not be embedded. so not embedding");
			return PDFHummus::eSuccess;
		}

		outEmbeddedFontObjectID = inObjectsContext->StartNewIndirectObject();
		
		DictionaryContext* fontProgramDictionaryContext = inObjectsContext->StartDictionary();

		// Length1 (decompressed true type program length)

		fontProgramDictionaryContext->WriteKey(scLength1);
		fontProgramDictionaryContext->WriteIntegerValue(rawFontProgram.GetCurrentWritePosition());
		rawFontProgram.pubseekoff(0,std::ios_base::beg);
		PDFStream* pdfStream = inObjectsContext->StartPDFStream(fontProgramDictionaryContext);


		// now copy the created font program to the output stream
		InputStringBufferStream fontProgramStream(&rawFontProgram);
		OutputStreamTraits streamCopier(pdfStream->GetWriteStream());
		status = streamCopier.CopyToOutputStream(&fontProgramStream);
		if(status != PDFHummus::eSuccess)
		{
			TRACE_LOG("TrueTypeEmbeddedFontWriter::WriteEmbeddedFont, failed to copy font program into pdf stream");
			break;
		}


		inObjectsContext->EndPDFStream(pdfStream);
		delete pdfStream;
	}while(false);

	return status;
}
コード例 #4
0
ファイル: CIDFontWriter.cpp プロジェクト: abyr/HummusJS
void CIDFontWriter::WriteToUnicodeMap(ObjectIDType inToUnicodeMap)
{
	mObjectsContext->StartNewIndirectObject(inToUnicodeMap);
	PDFStream* pdfStream = mObjectsContext->StartPDFStream();
	IByteWriter* cmapWriteContext = pdfStream->GetWriteStream();
	PrimitiveObjectsWriter primitiveWriter(cmapWriteContext);
	unsigned long i = 1;
	UIntAndGlyphEncodingInfoVector::iterator it = mCharactersVector.begin() + 1; // skip 0 glyph
	unsigned long vectorSize = (unsigned long)mCharactersVector.size() - 1; // cause 0 is not there

	cmapWriteContext->Write((const Byte*)scCmapHeader,strlen(scCmapHeader));
	primitiveWriter.WriteHexString(scFourByteRangeStart);
	primitiveWriter.WriteHexString(scFourByteRangeEnd,eTokenSeparatorEndLine);
	cmapWriteContext->Write((const Byte*)scEndCodeSpaceRange,strlen(scEndCodeSpaceRange));

	if(vectorSize < 100)
		primitiveWriter.WriteInteger(vectorSize);
	else
		primitiveWriter.WriteInteger(100);
	primitiveWriter.WriteKeyword(scBeginBFChar);
	
	WriteGlyphEntry(cmapWriteContext,it->second.mEncodedCharacter,it->second.mUnicodeCharacters);
	++it;
	for(; it != mCharactersVector.end(); ++it,++i)
	{
		if(i % 100 == 0)
		{
			primitiveWriter.WriteKeyword(scEndBFChar);
			if(vectorSize - i < 100)
				primitiveWriter.WriteInteger(vectorSize - i);
			else
				primitiveWriter.WriteInteger(100);
			primitiveWriter.WriteKeyword(scBeginBFChar);
		}
		WriteGlyphEntry(cmapWriteContext,it->second.mEncodedCharacter,it->second.mUnicodeCharacters);
	}
	primitiveWriter.WriteKeyword(scEndBFChar);
	cmapWriteContext->Write((const Byte*)scCmapFooter,strlen(scCmapFooter));
	mObjectsContext->EndPDFStream(pdfStream);
	delete pdfStream;
}
コード例 #5
0
EStatusCode DCTDecodeFilterTest::ModifyImageObject(PDFWriter* inWriter,ObjectIDType inImageObject)
{
    EStatusCode status = eSuccess;
    PDFDocumentCopyingContext* modifiedFileContext = inWriter->CreatePDFCopyingContextForModifiedFile();
    
    do
    {
        // get image source dictionary
        PDFObjectCastPtr<PDFStreamInput> imageStream(inWriter->GetModifiedFileParser().ParseNewObject(inImageObject));
        
        RefCountPtr<PDFDictionary> imageDictionary(imageStream->QueryStreamDictionary());
        
        // strt object for modified image
        inWriter->GetObjectsContext().StartModifiedIndirectObject(inImageObject);
        
        DictionaryContext* newImageDictionary = inWriter->GetObjectsContext().StartDictionary();
        
        MapIterator<PDFNameToPDFObjectMap> it = imageDictionary->GetIterator();
        
        // copy all but "Filter" and "Length"
        ObjectIDTypeList indirectObjects;
        
        while (it.MoveNext())
        {
            if(it.GetKey()->GetValue() == "Filter" || it.GetKey()->GetValue() == "Length")
                continue;
            
            newImageDictionary->WriteKey(it.GetKey()->GetValue());
            EStatusCodeAndObjectIDTypeList result = modifiedFileContext->CopyDirectObjectWithDeepCopy(it.GetValue());
            if(result.first != eSuccess)
            {
                status = result.first;
                break;
            }
            indirectObjects.insert(indirectObjects.end(),result.second.begin(),result.second.end());
        }
        if(status != eSuccess)
            break;
        
        // start image stream for this dictionary (make sure it's unfiltered)
        PDFStream* newImageStream = inWriter->GetObjectsContext().StartUnfilteredPDFStream(newImageDictionary);
        
        // copy source stream through read filter
        IByteReader* sourceImage = modifiedFileContext->GetSourceDocumentParser()->StartReadingFromStream(imageStream.GetPtr());
        if(!sourceImage)
        {
            cout<<"failed to read DCT stream\n";
            status = eFailure;
            break;
        }
        
        OutputStreamTraits traits(newImageStream->GetWriteStream());
        status = traits.CopyToOutputStream(sourceImage);
        
        // finalize stream
        inWriter->GetObjectsContext().EndPDFStream(newImageStream);
        delete newImageStream;
 
        // late check for status so stream is deleted
        if(status != eSuccess)
            break;
        
        // copy remaining indirect objects from image stream dictionary
        status = modifiedFileContext->CopyNewObjectsForDirectObject(indirectObjects);
        
    }
    while (false);
    
    delete modifiedFileContext;
    return status;
    
}
コード例 #6
0
EStatusCode ObjectsContext::WriteXrefStream(DictionaryContext* inDictionaryContext)
{
    // k. complement input dictionary with the relevant entries - W and Index
    // then continue with a regular stream, forced to have "length" as direct object
    
    // write Index entry
    inDictionaryContext->WriteKey("Index");
    StartArray();
    
    ObjectIDType startID = 0;
    ObjectIDType firstIDNotInRange;
 
    while(startID < mReferencesRegistry.GetObjectsCount())
    {
        firstIDNotInRange = startID;
        
        // look for first ID that does not require update [for first version of PDF...it will be the end]
        while(firstIDNotInRange < mReferencesRegistry.GetObjectsCount() &&
              mReferencesRegistry.GetNthObjectReference(firstIDNotInRange).mIsDirty)
            ++firstIDNotInRange;
        
        // write section header
        mPrimitiveWriter.WriteInteger(startID);
        mPrimitiveWriter.WriteInteger(firstIDNotInRange - startID);
        
        startID = firstIDNotInRange;
        
        // now promote startID to the next object to update
        while(startID < mReferencesRegistry.GetObjectsCount() &&
              !mReferencesRegistry.GetNthObjectReference(startID).mIsDirty)
            ++startID;        
    }
    
    EndArray();
    EndLine();
    
    // write W entry, which is going to be 1 sizeof(long long) and sizeof(unsigned long), per the types i'm using
    
    size_t typeSize = 1;
    size_t locationSize = sizeof(LongFilePositionType);
    size_t generationSize = sizeof(unsigned long);
    
    inDictionaryContext->WriteKey("W");
    StartArray();
    WriteInteger(typeSize);
    WriteInteger(locationSize);
    WriteInteger(generationSize);
    EndArray();
    EndLine();
    
    // start the xref stream itself
    PDFStream* aStream = StartPDFStream(inDictionaryContext,true);
    
    // now write the table data itself
    EStatusCode status = eSuccess;
    ObjectIDType nextFreeObject = 0;
    
    do {
    
        for(ObjectIDType i = 0; i < mReferencesRegistry.GetObjectsCount() && eSuccess == status;++i)
        {
            if(!mReferencesRegistry.GetNthObjectReference(i).mIsDirty)
                continue;
     
            const ObjectWriteInformation& objectReference = mReferencesRegistry.GetNthObjectReference(i);

            if(objectReference.mObjectReferenceType == ObjectWriteInformation::Used)
            {
                // used object
                
                if(objectReference.mObjectWritten)
                {
                    WriteXrefNumber(aStream->GetWriteStream(),1,typeSize);
                    WriteXrefNumber(aStream->GetWriteStream(),objectReference.mWritePosition,locationSize);
                    WriteXrefNumber(aStream->GetWriteStream(),objectReference.mGenerationNumber,generationSize);
                }
                else
                {
                    // object not written. at this point this should not happen, and indicates a failure
                    status = PDFHummus::eFailure;
                    TRACE_LOG1("ObjectsContext::WriteXrefStream, Unexpected Failure. Object of ID = %ld was not registered as written. probably means it was not written",i);
                }
            }
            else 
            {
                // free object
                
                ++nextFreeObject;
                // look for next dirty & free object, to be the next item of linked list
                while(nextFreeObject < mReferencesRegistry.GetObjectsCount() &&
                      (!mReferencesRegistry.GetNthObjectReference(nextFreeObject).mIsDirty ||
                       mReferencesRegistry.GetNthObjectReference(nextFreeObject).mObjectReferenceType != ObjectWriteInformation::Free))
                    ++nextFreeObject;
                
                // if reached end of list, then link back to head - 0
                if(nextFreeObject == mReferencesRegistry.GetObjectsCount())
                    nextFreeObject = 0;
     
                WriteXrefNumber(aStream->GetWriteStream(),0,typeSize);
                WriteXrefNumber(aStream->GetWriteStream(),nextFreeObject,locationSize);
                WriteXrefNumber(aStream->GetWriteStream(),objectReference.mGenerationNumber,generationSize);
                
            }

        }
        
        if(status != eSuccess)
            break;
            
        // end the stream and g'bye
        EndPDFStream(aStream);

    } 
    while (false);

    return status;
}
コード例 #7
0
PDFHummus::EStatusCode PDFModifiedPage::WritePage()
{
	EStatusCode status = EndContentContext(); // just in case someone forgot to close the latest content context

	do {
		if (status != eSuccess || !mIsDirty) {
			break;
		}

		// allocate an object ID for the new contents stream (for placing the form)
		// we first create the modified page object, so that we can define a name for the new form xobject
		// that is unique
		ObjectsContext& objectContext = mWriter->GetObjectsContext();
		ObjectIDType newContentObjectID = objectContext.GetInDirectObjectsRegistry().AllocateNewObjectID();
		ObjectIDType newEncapsulatingObjectID = 0;


		// create a copying context, so we can copy the page dictionary, and modify its contents + resources dict
		PDFDocumentCopyingContext* copyingContext = mWriter->CreatePDFCopyingContextForModifiedFile();

		// get the page object
		ObjectIDType pageObjectID = copyingContext->GetSourceDocumentParser()->GetPageObjectID(mPageIndex);
		PDFObjectCastPtr<PDFDictionary> pageDictionaryObject = copyingContext->GetSourceDocumentParser()->ParsePage(mPageIndex);
		MapIterator<PDFNameToPDFObjectMap>  pageDictionaryObjectIt = pageDictionaryObject->GetIterator();

		// create modified page object
		objectContext.StartModifiedIndirectObject(pageObjectID);
		DictionaryContext* modifiedPageObject = mWriter->GetObjectsContext().StartDictionary();

		// copy all elements of the page to the new page object, but the "Contents", "Resources" and "Annots" elements
		while (pageDictionaryObjectIt.MoveNext())
		{
			if (pageDictionaryObjectIt.GetKey()->GetValue() != "Resources" &&
				pageDictionaryObjectIt.GetKey()->GetValue() != "Contents" &&
				pageDictionaryObjectIt.GetKey()->GetValue() != "Annots")
			{
				modifiedPageObject->WriteKey(pageDictionaryObjectIt.GetKey()->GetValue());
				copyingContext->CopyDirectObjectAsIs(pageDictionaryObjectIt.GetValue());
			}
		}

		// Write new annotations entry, joining existing annotations, and new ones (from links attaching or what not)
		if (pageDictionaryObject->Exists("Annots") || mWriter->GetDocumentContext().GetAnnotations().size() > 0)
		{
			modifiedPageObject->WriteKey("Annots");
			objectContext.StartArray();

			// write old annots, if any exist
			if(pageDictionaryObject->Exists("Annots")) {
				PDFObjectCastPtr<PDFArray> anArray(copyingContext->GetSourceDocumentParser()->QueryDictionaryObject(pageDictionaryObject.GetPtr(), "Annots"));
				SingleValueContainerIterator<PDFObjectVector> refs = anArray->GetIterator();
				while (refs.MoveNext())
					copyingContext->CopyDirectObjectAsIs(refs.GetItem());

			}

			// write new annots from links
			ObjectIDTypeSet& annotations = mWriter->GetDocumentContext().GetAnnotations();
			if (annotations.size() > 0)
			{
				ObjectIDTypeSet::iterator it = annotations.begin();
				for (; it != annotations.end(); ++it)
					objectContext.WriteNewIndirectObjectReference(*it);
			}
			annotations.clear();
			objectContext.EndArray(eTokenSeparatorEndLine);

		}

		// Write new contents entry, joining the existing contents with the new one. take care of various scenarios of the existing Contents
		modifiedPageObject->WriteKey("Contents");
		if (!pageDictionaryObject->Exists("Contents"))
		{	// no contents
			objectContext.WriteIndirectObjectReference(newContentObjectID);
		}
		else
		{
			objectContext.StartArray();
			if (mEnsureContentEncapsulation)
			{
				newEncapsulatingObjectID = objectContext.GetInDirectObjectsRegistry().AllocateNewObjectID();
				objectContext.WriteNewIndirectObjectReference(newEncapsulatingObjectID);
			}

			RefCountPtr<PDFObject> pageContent(copyingContext->GetSourceDocumentParser()->QueryDictionaryObject(pageDictionaryObject.GetPtr(), "Contents"));
			if (pageContent->GetType() == PDFObject::ePDFObjectStream)
			{
				// single content stream. must be a refrence which points to it
				PDFObjectCastPtr<PDFIndirectObjectReference> ref(pageDictionaryObject->QueryDirectObject("Contents"));
				objectContext.WriteIndirectObjectReference(ref->mObjectID, ref->mVersion);
			}
			else if (pageContent->GetType() == PDFObject::ePDFObjectArray)
			{
				PDFArray* anArray = (PDFArray*)pageContent.GetPtr();

				// multiple content streams
				SingleValueContainerIterator<PDFObjectVector> refs = anArray->GetIterator();
				PDFObjectCastPtr<PDFIndirectObjectReference> ref;
				while (refs.MoveNext())
				{
					ref = refs.GetItem();
					objectContext.WriteIndirectObjectReference(ref->mObjectID, ref->mVersion);
				}

			}
			else {
				// this basically means no content...or whatever. just ignore.
			}

			objectContext.WriteNewIndirectObjectReference(newContentObjectID);
			objectContext.EndArray();
			objectContext.EndLine();
		}

		// Write a new resource entry. copy all but the "XObject" entry, which needs to be modified. Just for kicks i'm keeping the original 
		// form (either direct dictionary, or indirect object)
		ObjectIDType resourcesIndirect = 0;
		ObjectIDType newResourcesIndirect = 0;
		vector<string> formResourcesNames;

		modifiedPageObject->WriteKey("Resources");
		if (!pageDictionaryObject->Exists("Resources"))
		{
			// check if there's inherited dict. if so - write directly as a modified version
			PDFObjectCastPtr<PDFDictionary> parentDict(
				pageDictionaryObject->Exists("Parent") ? 
					copyingContext->GetSourceDocumentParser()->QueryDictionaryObject(pageDictionaryObject.GetPtr(), "Parent"): 
					NULL);
			if(!parentDict) {
				formResourcesNames = WriteNewResourcesDictionary(objectContext);
			}
			else {
				PDFObjectCastPtr<PDFDictionary> inheritedResources = findInheritedResources(copyingContext->GetSourceDocumentParser(),parentDict.GetPtr());
				if(!inheritedResources) {
					formResourcesNames = WriteNewResourcesDictionary(objectContext);
				} else {
					formResourcesNames = WriteModifiedResourcesDict(copyingContext->GetSourceDocumentParser(), inheritedResources.GetPtr(), objectContext, copyingContext);
				}
			}
		}
		else
		{
			// resources may be direct, or indirect. if direct, write as is, adding the new form xobject, otherwise wait till page object ends and write then
			PDFObjectCastPtr<PDFIndirectObjectReference> resourceDictRef(pageDictionaryObject->QueryDirectObject("Resources"));
			if (!resourceDictRef)
			{
				PDFObjectCastPtr<PDFDictionary> resourceDict(pageDictionaryObject->QueryDirectObject("Resources"));
				formResourcesNames = WriteModifiedResourcesDict(copyingContext->GetSourceDocumentParser(), resourceDict.GetPtr(), objectContext, copyingContext);
			}
			else
			{
				resourcesIndirect = resourceDictRef->mObjectID;
				// later will write a modified version of the resources dictionary, with the new form.
				// only modify the resources dict object if wasn't already modified (can happen when sharing resources dict between multiple pages).
				// in the case where it was alrady modified, create a new resources dictionary that's a copy, and use it instead, to avoid overwriting
				// the previous modification
				GetObjectWriteInformationResult res = objectContext.GetInDirectObjectsRegistry().GetObjectWriteInformation(resourcesIndirect);
				if (res.first && res.second.mIsDirty)
				{
					newResourcesIndirect = objectContext.GetInDirectObjectsRegistry().AllocateNewObjectID();
					modifiedPageObject->WriteObjectReferenceValue(newResourcesIndirect);
				}
				else
					modifiedPageObject->WriteObjectReferenceValue(resourcesIndirect);
			}
		}

		objectContext.EndDictionary(modifiedPageObject);
		objectContext.EndIndirectObject();

		if (resourcesIndirect != 0)
		{
			if (newResourcesIndirect != 0)
				objectContext.StartNewIndirectObject(newResourcesIndirect);
			else
				objectContext.StartModifiedIndirectObject(resourcesIndirect);
			PDFObjectCastPtr<PDFDictionary> resourceDict(copyingContext->GetSourceDocumentParser()->ParseNewObject(resourcesIndirect));
			formResourcesNames = WriteModifiedResourcesDict(copyingContext->GetSourceDocumentParser(), resourceDict.GetPtr(), objectContext, copyingContext);
			objectContext.EndIndirectObject();
		}

		// if required write encapsulation code, so that new stream is independent of graphic context of original
		PDFStream* newStream;
		PrimitiveObjectsWriter primitivesWriter;
		if (newEncapsulatingObjectID != 0)
		{
			objectContext.StartNewIndirectObject(newEncapsulatingObjectID);
			newStream = objectContext.StartPDFStream();
			primitivesWriter.SetStreamForWriting(newStream->GetWriteStream());
			primitivesWriter.WriteKeyword("q");
			objectContext.EndPDFStream(newStream);

		}

		// last but not least, create the actual content stream object, placing the form
		objectContext.StartNewIndirectObject(newContentObjectID);
		newStream = objectContext.StartPDFStream();
		primitivesWriter.SetStreamForWriting(newStream->GetWriteStream());

		if (newEncapsulatingObjectID != 0) {
			primitivesWriter.WriteKeyword("Q");
		}

		vector<string>::iterator it = formResourcesNames.begin();
		for (; it != formResourcesNames.end(); ++it)
		{
			primitivesWriter.WriteKeyword("q");
			primitivesWriter.WriteInteger(1);
			primitivesWriter.WriteInteger(0);
			primitivesWriter.WriteInteger(0);
			primitivesWriter.WriteInteger(1);
			primitivesWriter.WriteInteger(0);
			primitivesWriter.WriteInteger(0);
			primitivesWriter.WriteKeyword("cm");
			primitivesWriter.WriteName(*it);
			primitivesWriter.WriteKeyword("Do");
			primitivesWriter.WriteKeyword("Q");
		}

		objectContext.EndPDFStream(newStream);
	} while (false);

	return status;
}