📄 pdfreader.cs
字号:
{
this.val = truthValue;
}
/// <summary>
/// Returns the string representation of this object.
/// </summary>
/// <returns>Either "true" or "false".</returns>
public override string ToString()
{
return val ? "true" : "false";
}
}
/// <summary>
/// Represents a form field in a PDF document.
/// Objects of this class should not be created directly, but rather by instantiating any of its subclasses.
/// </summary>
[CLSCompliant(true)]
public class PdfField
{
/// <summary>
/// The object number of this field.
/// </summary>
private int objectNumber;
/// <summary>
/// The generation number of this field.
/// </summary>
private int generationNumber;
/// <summary>
/// The field dictionary of this field. See the PDF Reference 8.6.2 Field Dictionaries.
/// </summary>
private PdfDictionary fieldDictionary;
/// <summary>
/// The serialized form of the object after it was parsed.
/// </summary>
private string original;
/// <summary>
/// The /AP PDF Name object.
/// </summary>
protected static PdfName APName = new PdfName("/AP");
/// <summary>
/// The /N PDF Name object.
/// </summary>
protected static PdfName NName = new PdfName("/N");
/// <summary>
/// The /V PDF Name object.
/// </summary>
protected static PdfName VName = new PdfName("/V");
/// <summary>
/// The /T PDF Name object.
/// </summary>
protected static PdfName TName = new PdfName("/T");
/// <summary>
/// The /Ff PDF Name object.
/// </summary>
protected static PdfName FFName = new PdfName("/Ff");
/// <summary>
/// The /FT PDF Name object.
/// </summary>
protected static PdfName FTName = new PdfName("/FT");
/// <summary>
/// The /Tx PDF Name object.
/// </summary>
protected static PdfName TXName = new PdfName("/Tx");
/// <summary>
/// The /Ch PDF Name object.
/// </summary>
protected static PdfName CHName = new PdfName("/Ch");
/// <summary>
/// The /Btn PDF Name object.
/// </summary>
protected static PdfName ButtonName = new PdfName("/Btn");
/// <summary>
/// The /Kids PDF Name object.
/// </summary>
protected static PdfName KidsName = new PdfName("/Kids");
/// <summary>
/// The /AA PDF Name object.
/// </summary>
protected static PdfName AAName = new PdfName("/AA");
/// <summary>
/// The /TM PDF Name object.
/// </summary>
protected static PdfName TMName = new PdfName("/TM");
/// <summary>
/// The /TU PDF Name object.
/// </summary>
protected static PdfName TUName = new PdfName("/TU");
/// <summary>
/// The /Parent PDF Name object.
/// </summary>
protected static PdfName ParentName = new PdfName("/Parent");
/// <summary>
/// The object number of this field.
/// </summary>
public int ObjectNumber
{
get
{
return objectNumber;
}
set
{
objectNumber = value;
}
}
/// <summary>
/// The generation number of this field.
/// </summary>
public int GenerationNumber
{
get
{
return generationNumber;
}
set
{
generationNumber = value;
}
}
/// <summary>
/// The field dictionary of this field. See the PDF Reference 8.6.2 Field Dictionaries.
/// </summary>
public PdfDictionary FieldDictionary
{
get
{
return fieldDictionary;
}
set
{
fieldDictionary = value;
}
}
/// <summary>
/// Initializes a new instance of PdfField with the specified object number, generation number,
/// and field dictionary.
/// </summary>
/// <param name="objNumber">The object number.</param>
/// <param name="generationNumber">The generation number.</param>
/// <param name="fieldDictionary">The field dictionary.</param>
protected PdfField(int objNumber, int generationNumber, PdfDictionary fieldDictionary)
{
ObjectNumber = objNumber;
GenerationNumber = generationNumber;
FieldDictionary = fieldDictionary;
original = GetString();
}
/// <summary>
/// Factory method for PdfField objects.
/// Initializes new objects according to the contents of the specified field dictionary.
/// Does not currently support signature fields.
/// In most cases, this will return just one object. However, fields are organized according
/// to trees, where intermediate field objects may have child fields. Only terminal field objects
/// are "real" fields, so this method may return more than one field.
/// </summary>
/// <param name="reference">The reference to the root node of the fields.</param>
/// <param name="reader">The PdfReader object from which to fetch additional child objects.</param>
/// <param name="parentDictionary">The accumulated field dictionary of the ancestor objects.
/// May be null for the root object.</param>
/// <param name="fieldName">The complete field name up to this object, e.g. "a.b.c".</param>
/// <returns>A new PdfField object.</returns>
/// <exception cref="Exception">Thrown when the field dictionary does not contain
/// a known field type.</exception>
public static PdfField[] GetPdfFields(PdfReference reference, PdfReader reader,
PdfDictionary parentDictionary, string fieldName)
{
int objNumber = reference.ObjectNumber;
int generationNumber = reference.GenerationNumber;
PdfDictionary fieldDictionary = (PdfDictionary)reader.GetObjectForReference(reference);
// get the path name
if (fieldDictionary["/T"] != null)
{
if (fieldName != "")
{
fieldName += ".";
}
fieldName += ((PdfString)fieldDictionary["/T"]).Text;
}
if (parentDictionary != null)
{
// add all ancestral objects that haven't been overwritten by this object
foreach (object key in parentDictionary.Dictionary.Keys)
{
if (!fieldDictionary.Dictionary.ContainsKey(key))
{
fieldDictionary.Dictionary.Add(key, parentDictionary.Dictionary[key]);
}
}
}
if (fieldDictionary["/Kids"] == null || PdfButtonField.IsRadioButton(fieldDictionary))
{
// it's a terminal node
PdfName fieldType = (PdfName)fieldDictionary.GetElement(FTName);
PdfField field;
if (fieldType.Equals(TXName))
{
field = new PdfTXField(objNumber, generationNumber, fieldDictionary);
}
else if (fieldType.Equals(CHName))
{
field = new PdfCHField(objNumber, generationNumber, fieldDictionary);
}
else if (fieldType.Equals(ButtonName))
{
field = PdfButtonField.GetButtonField(objNumber, generationNumber, fieldDictionary);
}
else
{
throw new Exception("unsupported field type '" + fieldType.ToString() + "'");
}
field.FieldName = fieldName;
return new PdfField[] { field };
}
else
{
// it's an intermediate node
ArrayList fields = new ArrayList();
PdfArray kids = (PdfArray)fieldDictionary.GetElement(KidsName);
foreach (PdfReference child in kids.Elements)
{
PdfDictionary childDictionary = new PdfDictionary(new Hashtable(fieldDictionary.Dictionary));
// these are not inheritable
childDictionary.Dictionary.Remove(KidsName);
childDictionary.Dictionary.Remove(TName);
childDictionary.Dictionary.Remove(AAName);
childDictionary.Dictionary.Remove(TMName);
childDictionary.Dictionary.Remove(TUName);
childDictionary.Dictionary.Remove(ParentName);
fields.AddRange(GetPdfFields(child, reader, childDictionary, fieldName));
}
return (PdfField[])fields.ToArray(typeof(PdfField));
}
}
/// <summary>
/// Returns true if changes were made to the field after it was created.
/// </summary>
/// <returns>true if there are changes.</returns>
public bool HasChanged()
{
bool hasChanged = !original.Equals(ToString());
return hasChanged;
}
/// <summary>
/// Returns the string representation of this form field.
/// </summary>
/// <returns>The string representation of this form field.</returns>
public override string ToString()
{
return GetString();
}
private string GetString()
{
string s = ObjectNumber.ToString(CultureInfo.InvariantCulture) + " " + GenerationNumber + " obj\n";
s += FieldDictionary.ToString();
s += "\nendobj\n";
return s;
}
/// <summary>
/// Gets or sets the name of this field. This is not the complete field name, just the local part,
/// e.g. "c" where the complete field name is "a.b.c".
/// </summary>
/// <value>The name of this form field.</value>
public string Name
{
get
{
if (FieldDictionary.Dictionary.ContainsKey(TName) && FieldDictionary.Dictionary[TName].GetType() == typeof (PdfString))
{
PdfString name = (PdfString)FieldDictionary.Dictionary[TName];
return name.Text;
}
else
{
return "";
}
}
set
{
string s = "()";
PdfString name = new PdfString(false, ref s);
name.Text = value;
FieldDictionary.SetElement(TName, name);
}
}
/// <summary>
/// The complete field name.
/// </summary>
private string completeFieldName;
/// <summary>
/// Gets or Sets the complete field name.
/// </summary>
public string FieldName
{
get
{
return completeFieldName;
}
set
{
this.completeFieldName = value;
}
}
/// <summary>
/// Returns the bit at the specified position in the field flags of this field.
/// </summary>
/// <param name="bitPosition">The bit position starting at 1.</param>
/// <returns>true if the bit's value is 1.</returns>
public bool GetBit(int bitPosition)
{
bool bit = false;
if (FieldDictionary.Dictionary.ContainsKey(FFName) && FieldDictionary.Dictionary[FFName].GetType() == typeof (PdfNumber))
{
PdfNumber number = (PdfNumber)FieldDictionary.Dictionary[FFName];
bit = ((int)number.Number & (1 << (bitPosition - 1))) > 0;
}
return bit;
}
/// <summary>
/// Sets the bit at the specified position in the field flags of this field.
/// </summary>
/// <param name="bitPosition">The bit position starting at 1.</param>
/// <param name="bit">true to set the bit's value to 1.</param>
public void SetBit(int bitPosition, bool bit)
{
int num = 0;
if (FieldDictionary.Dictionary.ContainsKey(FFName) && FieldDictionary.Dictionary[FFName].GetType() == typeof (PdfNumber))
{
num = (int)((PdfNumber)FieldDictionary.Dictionary[FFName]).Number;
}
if (bit)
{
num = (int)num | (1 << (bitPosition - 1));
}
else
{
num = (int)num & ~(1 << (bitPosition - 1));
}
FieldDictionary.SetElement(FFName, new PdfNumber(num.ToString(CultureInfo.InvariantCulture)));
}
}
/// <summary>
/// Represents a generic Button form field in a PDF document.
/// Instances of this class should not be created through the constructor but instead through the factory
/// method <see cref="GetButtonField"/>.
/// See the PDF reference 8.6.3 Field Types.
/// </summary>
[CLSCompliant(true)]
public class PdfButtonField: PdfField
{
private static readonly Regex btnRegex = new Regex(@"/Ff\s+(\d+)", RegexOptions.Singleline);
/// <summary>
/// Initializes a new instance of PdfButtonField with the specified object number, generation number,
/// and field dictionary.
/// </summary>
/// <param name="objNumber">The object number.</param>
/// <param name="generationNumber">The generation number.</param>
/// <param name="fieldDictionary">The field dictionary.</param>
protected PdfButtonField(int objNumber, int generationNumber, PdfDictionary fieldDictionary): base(objNumber,
generationNumber, fieldDictionary)
{
}
/// <summary>
/// Creates either a <see cref="PdfPushButtonField"/>, <see cref="PdfRadioButtonField"/>, or a
/// <see cref="PdfCheckBoxField"/> according to the parsed field dictionary.
/// </summary>
/// <param name="objNumber">The object number.</param>
/// <param name="generationNumber">The generation number.</param>
/// <param name="fieldDictionary">The field dictionary.</param>
/// <returns></returns>
public static PdfButtonField GetButtonField(int objNumber, int generationNumber, PdfDictionary fieldDictionary)
{
int flags = 0;
PdfNumber num = (PdfNumber)fieldDictionary.GetElement(FFName);
if (num != null)
{
flags = (int)num.Number;
}
if ((flags & (1 << 16)) > 0)
{
return new PdfPushButtonField(objNumber, generationNumber, fieldDictionary);
}
else if ((flags & (1 << 15)) > 0)
{
return new PdfRadioButtonField(objNumber, generationNumber, fieldDictionary);
}
else
{
return new PdfCheckBoxField(objNumber, generationNumber, fieldDictionary);
}
}
/// <summary>
/// Determines whether the object specified is a RadioButton.
/// </summary>
/// <param name="fieldDictionary">The object's field dictionary.</param>
/// <returns>true if the object specified is a RadioButton, false otherwise.</returns>
public static bool IsRadioButton(PdfDictionary fieldDictionary)
{
if (!IsButton(fieldDictionary))
{
return false;
}
PdfNumber num = fieldDictionary.GetElement(FFName) as PdfNumber;
if (num != null)
{
int flags = (int)num.Number;
return ((flags & (1 << 15)) > 0);
}
else
{
return false;
}
}
/// <summary>
/// Determines whether the object specified is a Button.
/// </summary>
/// <param name="fieldDictionary">The object's field dictionary.</param>
/// <returns>true if the object specified is a Button, false otherwise.</returns>
protected static bool IsButton(PdfDictionary fieldDictionary)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -