private AcroFieldBase GetAcroField(DictionaryToken fieldDictionary, Catalog catalog) { fieldDictionary.TryGet(NameToken.Ft, out NameToken fieldType); fieldDictionary.TryGet(NameToken.Ff, out NumericToken fieldFlagsToken); var kids = new List <DictionaryToken>(); if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Kids, tokenScanner, out ArrayToken kidsToken)) { foreach (var kid in kidsToken.Data) { if (!(kid is IndirectReferenceToken kidReferenceToken)) { throw new PdfDocumentFormatException($"AcroForm kids should only contain indirect reference, instead got: {kid}."); } var kidObject = tokenScanner.Get(kidReferenceToken.Data); if (kidObject.Data is DictionaryToken kidDictionaryToken) { kids.Add(kidDictionaryToken); } else { throw new PdfDocumentFormatException($"Unexpected type of kid in AcroForm field. Expected dictionary but got: {kidObject.Data}."); } } } fieldDictionary.TryGetOptionalStringDirect(NameToken.T, tokenScanner, out var partialFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tu, tokenScanner, out var alternateFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tm, tokenScanner, out var mappingName); fieldDictionary.TryGet(NameToken.Parent, out IndirectReferenceToken parentReferenceToken); var information = new AcroFieldCommonInformation(parentReferenceToken?.Data, partialFieldName, alternateFieldName, mappingName); int?pageNumber = null; if (fieldDictionary.TryGet(NameToken.P, tokenScanner, out IndirectReferenceToken pageReference)) { pageNumber = catalog.GetPageByReference(pageReference.Data)?.PageNumber; } PdfRectangle?bounds = null; if (fieldDictionary.TryGet(NameToken.Rect, tokenScanner, out ArrayToken rectArray) && rectArray.Length == 4) { bounds = rectArray.ToRectangle(); } var fieldFlags = (uint)(fieldFlagsToken?.Long ?? 0); AcroFieldBase result; if (fieldType == null) { var children = new List <AcroFieldBase>(); foreach (var kid in kids) { var kidField = GetAcroField(kid, catalog); children.Add(kidField); } result = new AcroNonTerminalField(fieldDictionary, "Non-Terminal Field", fieldFlags, information, children); } else if (fieldType == NameToken.Btn) { var buttonFlags = (AcroButtonFieldFlags)fieldFlags; if (buttonFlags.HasFlag(AcroButtonFieldFlags.Radio)) { var field = new AcroRadioButtonsField(fieldDictionary, fieldType, buttonFlags, information, pageNumber, bounds); result = field; } else if (buttonFlags.HasFlag(AcroButtonFieldFlags.PushButton)) { var field = new AcroPushButtonField(fieldDictionary, fieldType, buttonFlags, information, pageNumber, bounds); result = field; } else { var isChecked = false; if (!fieldDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NameToken valueToken)) { valueToken = NameToken.Off; } else { isChecked = !string.Equals(valueToken.Data, NameToken.Off, StringComparison.OrdinalIgnoreCase); } var field = new AcroCheckboxField(fieldDictionary, fieldType, buttonFlags, information, valueToken, isChecked, pageNumber, bounds); result = field; } } else if (fieldType == NameToken.Tx) { result = GetTextField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); } else if (fieldType == NameToken.Ch) { result = GetChoiceField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); } else if (fieldType == NameToken.Sig) { var field = new AcroSignatureField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); result = field; } else { throw new PdfDocumentFormatException($"Unexpected type for field in AcroForm: {fieldType}."); } return(result); }
private AcroFieldBase GetAcroField(DictionaryToken fieldDictionary, Catalog catalog, IReadOnlyList <DictionaryToken> parentDictionaries) { var(combinedFieldDictionary, inheritsValue) = CreateInheritedDictionary(fieldDictionary, parentDictionaries); fieldDictionary = combinedFieldDictionary; fieldDictionary.TryGet(NameToken.Ft, tokenScanner, out NameToken fieldType); fieldDictionary.TryGet(NameToken.Ff, tokenScanner, out NumericToken fieldFlagsToken); var kids = new List <(bool hasParent, DictionaryToken dictionary)>(); if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Kids, tokenScanner, out ArrayToken kidsToken)) { foreach (var kid in kidsToken.Data) { if (!(kid is IndirectReferenceToken kidReferenceToken)) { throw new PdfDocumentFormatException($"AcroForm kids should only contain indirect reference, instead got: {kid}."); } var kidObject = tokenScanner.Get(kidReferenceToken.Data); if (kidObject.Data is DictionaryToken kidDictionaryToken) { var hasParent = kidDictionaryToken.TryGet(NameToken.Parent, out IndirectReferenceToken _); kids.Add((hasParent, kidDictionaryToken)); } else { throw new PdfDocumentFormatException($"Unexpected type of kid in AcroForm field. Expected dictionary but got: {kidObject.Data}."); } } } fieldDictionary.TryGetOptionalStringDirect(NameToken.T, tokenScanner, out var partialFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tu, tokenScanner, out var alternateFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tm, tokenScanner, out var mappingName); fieldDictionary.TryGet(NameToken.Parent, out IndirectReferenceToken parentReferenceToken); var information = new AcroFieldCommonInformation(parentReferenceToken?.Data, partialFieldName, alternateFieldName, mappingName); int?pageNumber = null; if (fieldDictionary.TryGet(NameToken.P, tokenScanner, out IndirectReferenceToken pageReference)) { pageNumber = catalog.GetPageByReference(pageReference.Data)?.PageNumber; } PdfRectangle?bounds = null; if (fieldDictionary.TryGet(NameToken.Rect, tokenScanner, out ArrayToken rectArray) && rectArray.Length == 4) { bounds = rectArray.ToRectangle(tokenScanner); } var newParentDictionaries = new List <DictionaryToken>(parentDictionaries) { fieldDictionary }; var children = new List <AcroFieldBase>(kids.Count); foreach (var kid in kids) { if (!kid.hasParent) { // Is a widget annotation dictionary. continue; } children.Add(GetAcroField(kid.dictionary, catalog, newParentDictionaries)); } var fieldFlags = (uint)(fieldFlagsToken?.Long ?? 0); AcroFieldBase result; if (fieldType == null) { result = new AcroNonTerminalField(fieldDictionary, "Non-Terminal Field", fieldFlags, information, AcroFieldType.Unknown, children); } else if (fieldType == NameToken.Btn) { var buttonFlags = (AcroButtonFieldFlags)fieldFlags; if (buttonFlags.HasFlag(AcroButtonFieldFlags.Radio)) { if (children.Count > 0) { result = new AcroRadioButtonsField(fieldDictionary, fieldType, buttonFlags, information, children); } else { var(isChecked, valueToken) = GetCheckedState(fieldDictionary, inheritsValue); var field = new AcroRadioButtonField(fieldDictionary, fieldType, buttonFlags, information, pageNumber, bounds, valueToken, isChecked); result = field; } } else if (buttonFlags.HasFlag(AcroButtonFieldFlags.PushButton)) { var field = new AcroPushButtonField(fieldDictionary, fieldType, buttonFlags, information, pageNumber, bounds); result = field; } else { if (children.Count > 0) { result = new AcroCheckboxesField(fieldDictionary, fieldType, buttonFlags, information, children); } else { var(isChecked, valueToken) = GetCheckedState(fieldDictionary, inheritsValue); var field = new AcroCheckboxField(fieldDictionary, fieldType, buttonFlags, information, valueToken, isChecked, pageNumber, bounds); result = field; } } } else if (fieldType == NameToken.Tx) { result = GetTextField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); } else if (fieldType == NameToken.Ch) { result = GetChoiceField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); } else if (fieldType == NameToken.Sig) { var field = new AcroSignatureField(fieldDictionary, fieldType, fieldFlags, information, pageNumber, bounds); result = field; } else { throw new PdfDocumentFormatException($"Unexpected type for field in AcroForm: {fieldType}."); } return(result); }
private AcroFieldBase GetAcroField(DictionaryToken fieldDictionary) { fieldDictionary.TryGet(NameToken.Ft, out NameToken fieldType); fieldDictionary.TryGet(NameToken.Ff, out NumericToken fieldFlagsToken); var kids = new List <DictionaryToken>(); if (fieldDictionary.TryGetOptionalTokenDirect(NameToken.Kids, tokenScanner, out ArrayToken kidsToken)) { foreach (var kid in kidsToken.Data) { if (!(kid is IndirectReferenceToken kidReferenceToken)) { throw new PdfDocumentFormatException($"AcroForm kids should only contain indirect reference, instead got: {kid}."); } var kidObject = tokenScanner.Get(kidReferenceToken.Data); if (kidObject.Data is DictionaryToken kidDictionaryToken) { kids.Add(kidDictionaryToken); } else { throw new PdfDocumentFormatException($"Unexpected type of kid in AcroForm field. Expected dictionary but got: {kidObject.Data}."); } } } fieldDictionary.TryGetOptionalStringDirect(NameToken.T, tokenScanner, out var partialFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tu, tokenScanner, out var alternateFieldName); fieldDictionary.TryGetOptionalStringDirect(NameToken.Tm, tokenScanner, out var mappingName); fieldDictionary.TryGet(NameToken.Parent, out IndirectReferenceToken parentReferenceToken); var information = new AcroFieldCommonInformation(parentReferenceToken?.Data, partialFieldName, alternateFieldName, mappingName); var fieldFlags = (uint)(fieldFlagsToken?.Long ?? 0); AcroFieldBase result; if (fieldType == null) { var children = new List <AcroFieldBase>(); foreach (var kid in kids) { var kidField = GetAcroField(kid); children.Add(kidField); } result = new NonTerminalAcroField(fieldDictionary, "Non-Terminal Field", fieldFlags, information, children); } else if (fieldType == NameToken.Btn) { var buttonFlags = (AcroButtonFieldFlags)fieldFlags; if (buttonFlags.HasFlag(AcroButtonFieldFlags.Radio)) { var field = new AcroRadioButtonsField(fieldDictionary, fieldType, buttonFlags, information); result = field; } else if (buttonFlags.HasFlag(AcroButtonFieldFlags.PushButton)) { var field = new AcroPushButtonField(fieldDictionary, fieldType, buttonFlags, information); result = field; } else { if (!fieldDictionary.TryGetOptionalTokenDirect(NameToken.V, tokenScanner, out NameToken valueToken)) { valueToken = NameToken.Off; } var field = new AcroCheckboxField(fieldDictionary, fieldType, buttonFlags, information, valueToken); result = field; } } else if (fieldType == NameToken.Tx) { result = GetTextField(fieldDictionary, fieldType, fieldFlags, information); } else if (fieldType == NameToken.Ch) { result = GetChoiceField(fieldDictionary, fieldType, fieldFlags, information); } else if (fieldType == NameToken.Sig) { var field = new AcroSignatureField(fieldDictionary, fieldType, fieldFlags, information); result = field; } else { throw new PdfDocumentFormatException($"Unexpected type for field in AcroForm: {fieldType}."); } return(result); }