/*
Copyright 2006,2007,2008 Stefano Chizzolini. http://clown.stefanochizzolini.it
Contributors:
* Stefano Chizzolini (original code developer, http://www.stefanochizzolini.it)
This file should be part of the source code distribution of "PDF Clown library"
(the Program): see the accompanying README files for more info.
This Program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later version.
This Program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY, either expressed or implied; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more details.
You should have received a copy of the GNU General Public License along with this
Program (see README files); if not, go to the GNU website (http://www.gnu.org/).
Redistribution and use, with or without modification, are permitted provided that such
redistributions retain the above copyright notice, license and disclaimer, along with
this list of conditions.
*/
using it.stefanochizzolini.clown.bytes;
using it.stefanochizzolini.clown.documents;
using it.stefanochizzolini.clown.documents.contents;
using it.stefanochizzolini.clown.objects;
using it.stefanochizzolini.clown.tokens;
using System;
using System.Collections;
using System.Text;
using System.IO;
namespace it.stefanochizzolini.clown.files{
/**
<summary>PDF file representation.</summary>
*/
public class File : IDisposable
{
#region static
#region fields
private static Random hashCodeGenerator = new Random();
#endregion
#region interface
#region public
/**
<summary>Forces a generic object to be expressed as its corresponding
data object.</summary>
*/
public static PdfDataObject Resolve(
PdfObject obj
)
{
if(obj is IPdfIndirectObject)
return ((IPdfIndirectObject)obj).DataObject;
else
return (PdfDataObject)obj;
}
/**
<summary>Forces a direct object to be updated (whether possible).</summary>
*/
public static bool Update(
PdfDirectObject obj
)
{
/*
NOTE: Only PDF references are able to be updated. Other direct types
are dependent on their respective containers for update.
*/
if(obj is PdfReference)
{
((PdfReference)obj).IndirectObject.Update();
return true;
}
return false;
}
#endregion
#endregion
#endregion
#region dynamic
#region fields
private Document document;
private int hashCode = File.hashCodeGenerator.Next();
private IndirectObjects indirectObjects;
private Reader reader;
private PdfDictionary trailer;
private string version;
private XRefEntry[] xrefEntries;
#endregion
#region constructors
public File(
)
{
this.version = "1.6";
this.trailer = new PdfDictionary();
this.indirectObjects = new IndirectObjects(this,null);
this.document = new Document(this);
}
public File(
string path
) : this(
new bytes.Stream(
new FileStream(
path,
FileMode.Open,
FileAccess.Read
)
)
)
{}
public File(
IInputStream stream
)
{
this.reader = new Reader(stream,this);
this.version = reader.ReadVersion();
this.trailer = reader.ReadTrailer();
// Is this file encrypted?
if(trailer.ContainsKey(PdfName.Encrypt))
throw new NotImplementedException("Encrypted files are currently not supported.");
this.xrefEntries = reader.ReadXRefTable(trailer);
this.indirectObjects = new IndirectObjects(this,xrefEntries);
this.document = new Document(trailer[PdfName.Root]);
}
#endregion
#region interface
#region public
public Document Document
{get{return document;}}
public override int GetHashCode(
)
{return hashCode;}
public IndirectObjects IndirectObjects
{get{return indirectObjects;}}
public Reader Reader
{get{return reader;}}
/**
<summary>Registers an <b>internal data object</b>.</summary>
*/
public PdfReference Register(
PdfDataObject obj
)
{return indirectObjects.Add(obj).Reference;}
public PdfDictionary Trailer
{get{return trailer;}}
/**
<summary>Unregisters an <b>internal object</b>.</summary>
*/
public void Unregister(
PdfReference reference
)
{indirectObjects.RemoveAt(reference.ObjectNumber);}
public string Version
{get{return version;}}
/**
<summary>Serializes the file to the specified file system path.</summary>
<param name="path">Target path.</param>
<param name="mode">Serialization mode.</param>
*/
public void WriteTo(
string path,
SerializationModeEnum mode
)
{
FileStream outputStream = new System.IO.FileStream(
path,
System.IO.FileMode.Create,
System.IO.FileAccess.Write
);
WriteTo(
new bytes.Stream(outputStream),
mode
);
outputStream.Flush();
outputStream.Close();
}
/**
<summary>Serializes the file to the specified stream.</summary>
<remarks>It's caller responsibility to close the stream after this method
ends.</remarks>
<param name="stream">Target stream.</param>
<param name="mode">Serialization mode.</param>
*/
public void WriteTo(
IOutputStream stream,
SerializationModeEnum mode
)
{
Writer writer = new Writer(stream,this);
switch(mode)
{
case SerializationModeEnum.Incremental:
if(reader == null)
goto case SerializationModeEnum.Standard;
writer.WriteIncremental();
break;
case SerializationModeEnum.Standard:
writer.WriteStandard();
break;
case SerializationModeEnum.Linearized:
throw new NotImplementedException();
}
}
//TODO:IMPL avoid direct exposure of array (corruptible!)!!!
public XRefEntry[] XRefEntries
{get{return xrefEntries;}}
#region IDisposable
public void Dispose(
)
{
if(reader != null)
{
reader.Dispose();
reader = null;
}
GC.SuppressFinalize(this);
}
#endregion
#endregion
#endregion
#endregion
}
}
|