Attached a project to demonstrate some issues we're seeing that need resolving in order to use the component.
1. When using a font like Tahoma on a form field, the value no longer displays or contains garbled text.
2. Input file is 24KB, output is 2MB!
3. Rotated field lose their rotation after being flattened.
4. Simulate merging with other files, 100 times the file is now 150MB! It's as though it's not re-using the fonts, but keeps adding the same ones.
5. when merging, but not flattening, the form fields are all lost on pages after page 1.
using System;using System.Collections.Generic;using System.IO;using System.Linq;using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf;using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.Streaming;using Telerik.Windows.Documents.Fixed.Model;using Telerik.Windows.Documents.Fixed.Model.Annotations;using Telerik.Windows.Documents.Fixed.Model.Editing;using Telerik.Windows.Documents.Fixed.Model.InteractiveForms;using Telerik.Windows.Documents.Fixed.Model.Resources;namespace FlattenFormFieldsDemo{ class Program { static void Main(string[] args) { PdfFormatProvider provider = new PdfFormatProvider(); RadFixedDocument document = provider.Import(File.ReadAllBytes("InteractiveForms.pdf")); foreach (RadFixedPage page in document.Pages) { foreach (Annotation annotation in page.Annotations) { if (annotation.Type == AnnotationType.Widget) { Widget widget = (Widget) annotation; if (widget.Field is TextBoxField field) { field.Value = "John Doe"; } } } } FlattenFormFields(document); string resultFile = "Flattened.pdf"; if(File.Exists(resultFile)) { File.Delete(resultFile); } File.WriteAllBytes(resultFile, provider.Export(document)); MergeMultipleFiles(resultFile); } public static void MergeMultipleFiles(string filename) { using (PdfStreamWriter fileWriter = new PdfStreamWriter(File.OpenWrite("MergedFlattened.pdf"))) { // Iterate through the files you would like to merge for(int i = 0; i< 100; i++) { // Open each of the files using (PdfFileSource fileToMerge = new PdfFileSource(File.OpenRead(filename))) { // Iterate through the pages of the current document foreach (PdfPageSource pageToMerge in fileToMerge.Pages) { // Append the current page to the fileWriter, which holds the stream of the result file fileWriter.WritePage(pageToMerge); } } } } } public static void FlattenFormFields(RadFixedDocument document) { foreach (RadFixedPage page in document.Pages) { List<Widget> widgetsToRemove = new List<Widget>(); FixedContentEditor pageEditor = new FixedContentEditor(page); foreach (Annotation annotation in page.Annotations) { if (annotation.Type == AnnotationType.Widget) { Widget widget = (Widget)annotation; FlattenWidgetAppearance(pageEditor, widget); widgetsToRemove.Add(widget); } } foreach (Widget widget in widgetsToRemove) { page.Annotations.Remove(widget); } } foreach (FormField field in document.AcroForm.FormFields.ToArray()) { document.AcroForm.FormFields.Remove(field); } } private static void FlattenWidgetAppearance(FixedContentEditor pageEditor, Widget widget) { FormSource widgetAppearance = GetWidgetNormalAppearance(widget); if (widgetAppearance == null) return; pageEditor.Position.Translate(widget.Rect.Left, widget.Rect.Top); pageEditor.DrawForm(widgetAppearance, widget.Rect.Width, widget.Rect.Height); } private static FormSource GetWidgetNormalAppearance(Widget widget) { FormSource widgetAppearance; switch (widget.WidgetContentType) { case WidgetContentType.PushButtonContent: widgetAppearance = ((PushButtonWidget)widget).Content.NormalContentSource; break; case WidgetContentType.SignatureContent: widgetAppearance = ((SignatureWidget)widget).Content.NormalContentSource; break; case WidgetContentType.VariableContent: widgetAppearance = ((VariableContentWidget)widget).Content.NormalContentSource; break; case WidgetContentType.TwoStatesContent: TwoStatesButtonWidget twoStatesWidget = (TwoStatesButtonWidget)widget; widgetAppearance = GetTwoStatesWidgetNormalAppearance(twoStatesWidget); break; default: throw new NotSupportedException(string.Format("Not supported widget content type {0}", widget.WidgetContentType)); } return widgetAppearance; } private static FormSource GetTwoStatesWidgetNormalAppearance(TwoStatesButtonWidget twoStatesWidget) { FormField field = twoStatesWidget.Field; bool isOnState; switch (field.FieldType) { case FormFieldType.CheckBox: CheckBoxField checkBox = (CheckBoxField) field; isOnState = checkBox.IsChecked; break; case FormFieldType.RadioButton: RadioButtonField radio = (RadioButtonField) field; RadioButtonWidget radioWidget = (RadioButtonWidget) twoStatesWidget; if (radio.ShouldUpdateRadiosInUnison) { isOnState = radio.Value != null && radio.Value.Value.Equals(radioWidget.Option.Value); } else { isOnState = radio.Value == radioWidget.Option; } break; default: throw new NotSupportedException(string.Format("Not supported field type {0} for TwoStateButtonWidget", field.FieldType)); } FormSource widgetAppearance = (isOnState ? twoStatesWidget.OnStateContent : twoStatesWidget.OffStateContent).NormalContentSource; return widgetAppearance; } }}
