// Copyright (C) 2003-2026, Foxit Software Inc..
// All Rights Reserved.
//
// http://www.foxitsoftware.com
//
// The following code is copyrighted and contains proprietary information and trade secrets of Foxit Software Inc..
// You cannot distribute any part of Foxit PDF SDK to any third party or general public,
// unless there is a separate license agreement with Foxit Software Inc. which explicitly grants you such rights.
//
// This file contains an example to demonstrate how to use Foxit PDF SDK to add various annotations to PDF document.

using System;
using System.Collections.Generic;

using foxit;
using foxit.common;
using foxit.common.fxcrt;
using foxit.pdf;
using foxit.pdf.graphics;
using foxit.pdf.annots;
using foxit.pdf.actions;
using foxit.pdf.objects;
using System.IO;
using System.Runtime.InteropServices;

namespace annotationCS
{
    class IconProvider : IconProviderCallback
    {
        private Dictionary<string, PDFDoc> pdf_doc_map_;
        private Dictionary<PDFDoc, PDFPage> pdf_page_0_map_;
        private string file_folder_;
        private bool use_dynamic_stamp_;
        private PDFDoc doc = null;
        public IconProvider(string file_folder)
        {
            this.file_folder_ = file_folder;
            this.use_dynamic_stamp_ = false;
            this.pdf_doc_map_ = new Dictionary<string, PDFDoc>();
            this.pdf_page_0_map_ = new Dictionary<PDFDoc, PDFPage>();
        }

        public override void Release()
        {
            foreach (PDFPage page in pdf_page_0_map_.Values)
            {
                page.Dispose();
            }

            foreach (PDFDoc doc in pdf_doc_map_.Values)
            {
                doc.Dispose();
            }
        }

        // If one icon provider offers different style icon for one icon name of a kind of annotaion,
        // please use different provider ID or version in order to distinguish different style for Foxit PDF SDK.
        // Otherwise, only the first style icon for the same icon name of same kind of annotation will have effect.
        public override string GetProviderID()
        {
            if (use_dynamic_stamp_)
            {
                return "Simple Demo Dynamic IconProvider";
            }
            else
            {
                return "Simple Demo IconProvider";
            }
        }

        public override String GetProviderVersion()
        {
            return "1.0.0";
        }

        public override bool HasIcon(Annot.Type annot_type, String icon_name)
        {
            String path;
            if (use_dynamic_stamp_)
            {
                path = file_folder_ + "/DynamicStamps/" + icon_name + ".pdf";
            }
            else
            {
                path = file_folder_ + "/StaticStamps/" + icon_name + ".pdf";
            }
            Boolean bContainsKey = pdf_doc_map_.ContainsKey(path);

            if (bContainsKey != false)
            {
                doc = pdf_doc_map_[path];
                return !doc.IsEmpty();
            }

            doc = new PDFDoc(path);

            try
            {

                ErrorCode error_code = doc.Load(null);
                if (ErrorCode.e_ErrSuccess == error_code)
                {
                    pdf_doc_map_.Add(path, doc);
                }
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            return !doc.IsEmpty();
        }

        public override bool CanChangeColor(Annot.Type annot_type, String icon_name)
        {
            return false;
        }

        public override PDFPage GetIcon(Annot.Type annot_type, String icon_name, uint color, PDFDictionary dict)
        {
            String path;
            if (use_dynamic_stamp_)
            {
                path = file_folder_ + "/DynamicStamps/" + icon_name + ".pdf";
            }
            else
            {
                path = file_folder_ + "/StaticStamps/" + icon_name + ".pdf";
            }
            Boolean bContainsKey = pdf_doc_map_.ContainsKey(path);
            PDFDoc doc = null;
            if (bContainsKey)
            {
                doc = pdf_doc_map_[path];
            }
            else
            {
                doc = new PDFDoc();
                pdf_doc_map_.Add(path, doc);
            }
            if (doc.IsEmpty() || doc.GetPageCount() == 0)
                return null;

            PDFPage page = null;
            bContainsKey = pdf_page_0_map_.ContainsKey(doc);
            if (bContainsKey)
            {
                page = pdf_page_0_map_[doc];
            }
            else
            {
                page = doc.GetPage(0);
                pdf_page_0_map_.Add(doc, page);
            }

            return page;
        }

        public override bool GetShadingColor(Annot.Type annot_type, string icon_name, int referenced_color, int shading_index, ShadingColor out_shading_color)
        {
            return false;
        }

        public override float GetDisplayWidth(Annot.Type annot_type, string icon_name)
        {
            return 0.0f;
        }

        public override float GetDisplayHeight(Annot.Type annot_type, String icon_name)
        {
            return 0.0f;
        }

        public void SetUseDynamicStamp(bool use_dynamic_stamp)
        {
            use_dynamic_stamp_ = use_dynamic_stamp;
        }
    };

    class ActionEvent : ActionCallback
    {
        public ActionEvent() { }
        public ActionEvent(PDFDoc document) { current_doc_ = document; }
        public override void Release() { }
        public override bool InvalidateRect(PDFDoc document, int page_index, RectF pdf_rect)
        {
            return false;
        }
        public override int GetCurrentPage(PDFDoc document)
        {
            return -1;
        }
        public override void SetCurrentPage(PDFDoc document, int page_index) { }
        public override Rotation GetPageRotation(PDFDoc document, int page_index)
        {
            return Rotation.e_Rotation0;
        }
        public override bool SetPageRotation(PDFDoc document, int page_index, Rotation rotation)
        {
            return false;
        }
        public override bool ExecuteNamedAction(PDFDoc document, string named_action)
        {
            return false;
        }
        public override bool SetDocChangeMark(PDFDoc document, bool change_mark)
        {
            return false;
        }
        public override bool GetDocChangeMark(PDFDoc document)
        {
            return false;
        }
        public override int GetOpenedDocCount()
        {
            return -1;
        }
        public override PDFDoc GetOpenedDoc(int index)
        {
            return current_doc_;
        }
        public override PDFDoc GetCurrentDoc() {
            return current_doc_;
        }
        public override PDFDoc CreateBlankDoc() {
            return new PDFDoc();
        }
        public override PDFDoc OpenDoc(string file_path, string password) {
            return new PDFDoc(file_path);
        }
        public override bool Beep(int type)
        {
            return false;
        }
        public override string Response(string question, string title, string default_value, string label, bool is_password)
        {
            return "";
        }
        public override string GetFilePath(PDFDoc document)
        {
            return "";
        }
        public override bool Print(PDFDoc document, bool is_ui, Range page_range, bool is_silent, bool is_shrunk_to_fit, bool is_printed_as_image, bool is_reversed, bool is_to_print_annots)
        {
            return false;
        }
        public override bool SubmitForm(PDFDoc document, IntPtr form_data, int length, string url, FileFormatType file_format_type)
        {
            return false;
        }
        public override bool LaunchURL(string url)
        {
            return false;
        }
        public override string BrowseFile()
        {
            return "";
        }
        public override string BrowseFile(bool is_open_dialog, string file_format, string file_filter)
        {
            return "";
        }
        public override ActionCallback.Language GetLanguage()
        {
            return ActionCallback.Language.e_LanguageCHS;
        }
        public override int Alert(string msg, string title, int type, int icon)
        {
            return 0;
        }
        public override IdentityProperties GetIdentityProperties()
        {
            return new IdentityProperties("foxitsoftware", "simple_demo@foxitsoftware.cn", "simple demo", "Simple", "simple", "demo", "developer", "gsdk");
        }
        public override bool SetIdentityProperties(IdentityProperties identity_properties)
        {
            return false;
        }
        public override string PopupMenu(MenuListArray menus, ref bool is_selected_item)
        {
            return "";
        }
        public override MenuItemEx PopupMenuEx(MenuItemExArray menus, ref bool is_selected_item)
        {
            return new MenuItemEx();
        }

        public override string GetAppInfo(ActionCallback.AppInfoType type)
        {
            return "";
        }
        public override bool MailData(IntPtr data, ActionCallback.MailType data_type, bool is_ui, string to, string subject, string cc, string bcc, string message)
        {
            return false;
        }
        public override uint VerifySignature(PDFDoc document, Signature pdf_signature)
        {
            return Convert.ToUInt32(foxit.pdf.Signature.States.e_StateUnknown);
        }
        public override string GetUntitledBookmarkName()
        {
            return "Untitled";
        }
        public override WStringArray GetPrinterNameList()
        {
            return new WStringArray();
        }
        public override bool AddToolButton(ButtonItem button_item)
        {
            return false;
        }
        public override bool RemoveToolButtom(string button_name)
        {
            return false;
        }
        public override MenuListArray GetMenuItemNameList()
        {
            return new MenuListArray();
        }
        public override bool AddMenuItem(MenuItemConfig menu_item_config, bool is_prepend)
        {
            return false;
        }
        public override bool AddSubMenu(MenuItemConfig menu_item_config)
        {
            return false;
        }
        public override bool ShowDialog(DialogDescriptionConfig dlg_config)
        {
            return false;
        }
        public override bool GetFullScreen()
        {
            return false;
        }
        public override void SetFullScreen(bool is_full_scree) { }

        public override void OnFieldValueChanged(string field_name, ActionCallback.JSFieldValueChangeType type, WStringArray value_before_changed, WStringArray value_after_changed) { }

        public override MediaPlayerCallback OpenMediaPlayer(PlayerArgs player_args) { return null; }
        public override void CloseDoc(PDFDoc document, bool is_prompt_to_save) { }
        public override string GetAttachmentsFilePath(PDFDoc pdf_doc, string name) { return ""; }
        public override string GetExtractedEmbeddedFilePath(PDFDoc pdf_doc, string name) { return ""; }
        public override LayoutMode GetLayoutMode() { return LayoutMode.e_LayoutModeSinglePage; }
        public override PointF GetMousePosition() { return new PointF(); }
        public override float GetPageScale() { return 0; }
        public override RectF GetPageWindowRect(PDFDoc document, int page_index) { return new RectF(); }
        public override Destination.ZoomMode GetPageZoomMode() { return 0; }
        public override string GetTemporaryDirectory() { return ""; }
        public override string GetTemporaryFileName(PDFDoc document, string file_name) { return ""; }
        public override bool IsLocalFile(PDFDoc document) { return false; }
        public override JsMailResult MailDoc(PDFDoc document, string to_address, string cc_address, string bcc_address, string subject, string message, bool is_ui) { return 0; }
        public override bool Print(PDFDoc document, PrintParams print_params) { return false; }
        public override void Scroll(PointF point) { }
        public override void SelectPageNthWord(int page_index, int start_offset, int end_offset, bool is_show_selection) { }
        public override void SetCurrentPage(PDFDoc document, Destination destination) { }
        public override void SetLayoutMode(LayoutMode layout_mode, bool is_cover_mode) { }
        public override void SetPageScale(Destination.ZoomMode zoom_mode, Destination dest) { }
        public override void UpdateLogicalLabel() { }
        public override void Query(string keywords, SearchScope search_scope, foxit.pdf.actions.SearchOption search_option, string di_path) { }
        public override SearchIndexConfig AddSearchIndex(string di_path, bool is_selected) { return new SearchIndexConfig(); }
        public override bool RemoveSearchIndex(SearchIndexConfig search_index_config) { return false; }
        public override WStringArray GetSignatureAPStyleNameList() { return new WStringArray();}
        public override SOAPResponseInfo SoapRequest(foxit.pdf.actions.SOAPRequestProperties request_params) { return new SOAPResponseInfo(); }
        public override void NotifyBeginDoJob(PDFDoc document, JavascriptModifyItemInfo.JavascriptEventType event_type) {  }
        public override void NotifyAfterDataChange(PDFDoc document, JavascriptModifyItemInfo modify_item_info) {  }
        public override void NotifyEndDoJob(PDFDoc document, JavascriptModifyItemInfo.JavascriptEventType event_type) {  }
        public override bool InitModifyItem(PDFDoc document, ModifyItemType item_type, int page_index, string dict_name) { return true; }
        public override void ResetModifyItem(PDFDoc document) { }
        public override int GetVisiblePageCount(PDFDoc document) { return 0;}
        public override int GetVisiblePage(PDFDoc document, int index) { return -1;}

	    private PDFDoc current_doc_;
    };

    class annotation
    {
        public static string output_path = "../output_files/annotation/";
        public static string input_path = "../input_files/";
        static foxit.common.DateTime GetLocalDateTime()
        {
            System.DateTimeOffset rime = System.DateTimeOffset.Now;
            foxit.common.DateTime datetime = new foxit.common.DateTime();
            datetime.year = (UInt16)rime.Year;
            datetime.month = (UInt16)rime.Month;
            datetime.day = (ushort)rime.Day;
            datetime.hour = (UInt16)rime.Hour;
            datetime.minute = (UInt16)rime.Minute;
            datetime.second = (UInt16)rime.Second;

            datetime.utc_hour_offset = (short)rime.Offset.Hours;
            datetime.utc_minute_offset = (ushort)rime.Offset.Minutes;

            return datetime;
        }

        static String RandomUID()
        {
            return System.Guid.NewGuid().ToString();
        }
        
        static void AddAnnotations(PDFPage page, ActionEvent action_callback)
        {
            {
                // Add line annotation 
                // No special intent, as a common line.
                Line line = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Line, new RectF(0, 650, 100, 750)))
                {
                    using (line = new Line(annot))
                    {
                        //This flag is used for printing annotations.
                        line.SetFlags(4);
                        line.SetStartPoint(new foxit.common.fxcrt.PointF(20, 650));
                        line.SetEndPoint(new foxit.common.fxcrt.PointF(100, 740));
                        // Intent, as line arrow.
                        line.SetContent("A line arrow annotation");
                        line.SetIntent("LineArrow");
                        line.SetSubject("Arrow");
                        line.SetTitle("Foxit SDK");
                        line.SetCreationDateTime(GetLocalDateTime());
                        line.SetModifiedDateTime(GetLocalDateTime());
                        line.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        line.ResetAppearanceStream();
                    }
                    using (annot = page.AddAnnot(Annot.Type.e_Line, new RectF(0, 650, 100, 760)))
                    using (line = new Line(annot))
                    {
                        //This flag is used for printing annotations.
                        line.SetFlags(4);
                        // Set foxit RGB color
                        line.SetBorderColor(0x00FF00);
                        line.SetStartPoint(new foxit.common.fxcrt.PointF(10, 650));
                        line.SetEndPoint(new foxit.common.fxcrt.PointF(100, 750));
                        line.SetContent("A common line.");
                        line.SetLineStartStyle(Markup.EndingStyle.e_EndingStyleSquare);
                        line.SetLineEndStyle(Markup.EndingStyle.e_EndingStyleOpenArrow);
                        // Show text in line
                        line.EnableCaption(true);
                        line.SetCaptionOffset(new foxit.common.fxcrt.PointF(0, 5));

                        line.SetSubject("Line");
                        line.SetTitle("Foxit SDK");
                        line.SetCreationDateTime(GetLocalDateTime());
                        line.SetModifiedDateTime(GetLocalDateTime());
                        line.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        line.ResetAppearanceStream();
                        Console.WriteLine("Add a line annotations.");
                    }
                }
            }

            {
                // Add circle annotation
                Circle circle = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Circle, new RectF(100, 650, 200, 750)))
                using (circle = new Circle(annot))
                {
                    //This flag is used for printing annotations.
                    circle.SetFlags(4);
                    circle.SetInnerRect(new RectF(120, 660, 160, 740));
                    circle.SetSubject("Circle");
                    circle.SetTitle("Foxit SDK");
                    circle.SetCreationDateTime(GetLocalDateTime());
                    circle.SetModifiedDateTime(GetLocalDateTime());
                    circle.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    circle.ResetAppearanceStream();
                    Console.WriteLine("Add a circle annotation.");
                }
            }

            {
                // Add square annotation
                Square square = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Square, new RectF(200, 650, 300, 750)))
                using (square = new Square(annot))
                {
                    //This flag is used for printing annotations.
                    square.SetFlags(4);
                    square.SetFillColor(0x00FF00);
                    square.SetInnerRect(new RectF(220, 660, 260, 740));
                    square.SetSubject("Square");
                    square.SetTitle("Foxit SDK");
                    square.SetCreationDateTime(GetLocalDateTime());
                    square.SetModifiedDateTime(GetLocalDateTime());
                    square.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    square.ResetAppearanceStream();
                    Console.WriteLine("Add a square annotation.");
                }
            }

            {
                // Add polygon annotation, as cloud.
                Polygon polygon = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Polygon, new RectF(300, 650, 500, 750)))
                using (polygon = new Polygon(annot))
                {
                    //This flag is used for printing annotations.
                    polygon.SetFlags(4);
                    polygon.SetIntent("PolygonCloud");
                    polygon.SetFillColor(0x0000FF);
                    PointFArray vertexe_array = new PointFArray();
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(335, 665));
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(365, 665));
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(385, 705));
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(365, 740));
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(335, 740));
                    vertexe_array.Add(new foxit.common.fxcrt.PointF(315, 705));
                    polygon.SetVertexes(vertexe_array);
                    polygon.SetSubject("Cloud");
                    polygon.SetTitle("Foxit SDK");
                    polygon.SetCreationDateTime(GetLocalDateTime());
                    polygon.SetModifiedDateTime(GetLocalDateTime());
                    polygon.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    polygon.ResetAppearanceStream();
                    Console.WriteLine("Add a polygon annotation.");
                }
            }

            {
                // Add polygon annotation, with dashed border.
                using (BorderInfo borderinfo = new BorderInfo())
                {
                    borderinfo.cloud_intensity = 2.0f;
                    borderinfo.width = 2.0f;
                    borderinfo.style = BorderInfo.Style.e_Dashed;
                    borderinfo.dash_phase = 3.0f;
                    borderinfo.dashes.SetSize(2, -1);
                    borderinfo.dashes.SetAt(0, 2);
                    borderinfo.dashes.SetAt(1, 2);

                    Polygon polygon = null;
                    Annot annot = null;
                    using (annot = page.AddAnnot(Annot.Type.e_Polygon, new RectF(400, 650, 500, 750)))
                    using (polygon = new Polygon(annot))
                    {
                        //This flag is used for printing annotations.
                        polygon.SetFlags(4);
                        polygon.SetFillColor(0x0000FF);
                        polygon.SetBorderInfo(borderinfo);
                        using (PointFArray vertexe_array = new PointFArray())
                        {
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(435, 665));
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(465, 665));
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(485, 705));
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(465, 740));
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(435, 740));
                            vertexe_array.Add(new foxit.common.fxcrt.PointF(415, 705));

                            polygon.SetVertexes(vertexe_array);
                            polygon.SetSubject("Polygon");
                            polygon.SetTitle("Foxit SDK");
                            polygon.SetCreationDateTime(GetLocalDateTime());
                            polygon.SetModifiedDateTime(GetLocalDateTime());
                            polygon.SetUniqueID(RandomUID());
                            // Appearance should be reset.
                            polygon.ResetAppearanceStream();
                            Console.WriteLine("Add a polygon cloud annotation.");
                        }
                    }
                }
            }
            {
                // Add polyline annotation 
                PolyLine polyline = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_PolyLine, new RectF(500, 650, 600, 700)))
                {
                    PointFArray vertexe_array = new PointFArray();
                    using (polyline = new PolyLine(annot))
                    {
                        //This flag is used for printing annotations.
                        polyline.SetFlags(4);
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(515, 705));
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(535, 740));
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(565, 740));
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(585, 705));
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(565, 665));
                        vertexe_array.Add(new foxit.common.fxcrt.PointF(535, 665));
                        polyline.SetVertexes(vertexe_array);
                        polyline.SetSubject("PolyLine");
                        polyline.SetTitle("Foxit SDK");
                        polyline.SetCreationDateTime(GetLocalDateTime());
                        polyline.SetModifiedDateTime(GetLocalDateTime());
                        polyline.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        polyline.ResetAppearanceStream();
                        Console.WriteLine("Add a polyline annotation.");
                    }
                }
            }

            {
                // Add freetext annotation, as type writer.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(10, 550, 200, 600)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)(DefaultAppearance.DefAPFlags.e_FlagFont | DefaultAppearance.DefAPFlags.e_FlagFontSize | DefaultAppearance.DefAPFlags.e_FlagTextColor);
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelvetica))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        freetext.SetDefaultAppearance(default_ap);
                        freetext.SetIntent("FreeTextTypewriter");
                        freetext.SetContent("A typewriter annotation");
                        freetext.SetSubject("FreeTextTypewriter");
                        freetext.SetTitle("Foxit SDK");
                        freetext.SetCreationDateTime(GetLocalDateTime());
                        freetext.SetModifiedDateTime(GetLocalDateTime());
                        freetext.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        freetext.ResetAppearanceStream();
                        Console.WriteLine("Add a typewriter freetext annotation.");
                    }
                }
            }

            {
                // Add freetext annotation, as call-out.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(300, 550, 400, 600)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)DefaultAppearance.DefAPFlags.e_FlagFont | (int)DefaultAppearance.DefAPFlags.e_FlagFontSize | (int)DefaultAppearance.DefAPFlags.e_FlagTextColor;
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelveticaB))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        // Set default appearance for form.
                        freetext.SetDefaultAppearance(default_ap);
                        
                        freetext.SetIntent("FreeTextCallout");
                        using (PointFArray callout_points = new PointFArray())
                        using (foxit.common.fxcrt.PointF point1 = new foxit.common.fxcrt.PointF(250, 540))
                        using (foxit.common.fxcrt.PointF point2 = new foxit.common.fxcrt.PointF(280, 570))
                        using (foxit.common.fxcrt.PointF point3 = new foxit.common.fxcrt.PointF(300, 570))
                        {
                            callout_points.Add(point1);
                            callout_points.Add(point2);
                            callout_points.Add(point3);

                            freetext.SetCalloutLinePoints(callout_points);
                            freetext.SetCalloutLineEndingStyle(Markup.EndingStyle.e_EndingStyleOpenArrow);
                            freetext.SetContent("A callout annotation.");
                            freetext.SetSubject("FreeTextCallout");
                            freetext.SetTitle("Foxit SDK");
                            freetext.SetCreationDateTime(GetLocalDateTime());
                            freetext.SetModifiedDateTime(GetLocalDateTime());
                            freetext.SetUniqueID(RandomUID());
                            // Appearance should be reset.
                            freetext.ResetAppearanceStream();
                            Console.WriteLine("Add a callout freetext annotation.");
                        }
                    }
                }
            }

            {
                // Add freetext annotation, as text box.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(450, 550, 550, 600)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)DefaultAppearance.DefAPFlags.e_FlagFont | (int)DefaultAppearance.DefAPFlags.e_FlagFontSize | (int)DefaultAppearance.DefAPFlags.e_FlagTextColor;
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelveticaI))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        freetext.SetDefaultAppearance(default_ap);
                        freetext.SetContent("A text box annotation.");
                        freetext.SetSubject("Textbox");
                        freetext.SetTitle("Foxit SDK");
                        freetext.SetCreationDateTime(GetLocalDateTime());
                        freetext.SetModifiedDateTime(GetLocalDateTime());
                        freetext.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        freetext.ResetAppearanceStream();
                        Console.WriteLine("Add a text box freetext annotation.");
                    }
                }
            }

            {
                // Add highlight annotation.
                Highlight highlight = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Highlight, new RectF(10, 450, 100, 550)))
                using (highlight = new Highlight(annot))
                {
                    highlight.SetContent("Highlight");
                    //This flag is used for printing annotations.
                    highlight.SetFlags(4);
                    QuadPoints quad_points = new QuadPoints();
                    using (quad_points.first = new foxit.common.fxcrt.PointF(10, 500))
                    using (quad_points.second = new foxit.common.fxcrt.PointF(90, 500))
                    using (quad_points.third = new foxit.common.fxcrt.PointF(10, 480))
                    using (quad_points.fourth = new foxit.common.fxcrt.PointF(90, 480))
                    using (QuadPointsArray quad_points_array = new QuadPointsArray())
                    {
                        quad_points_array.Add(quad_points);
                        highlight.SetQuadPoints(quad_points_array);
                        highlight.SetSubject("Highlight");
                        highlight.SetTitle("Foxit SDK");
                        highlight.SetCreationDateTime(GetLocalDateTime());
                        highlight.SetModifiedDateTime(GetLocalDateTime());
                        highlight.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        highlight.ResetAppearanceStream();
                        Console.WriteLine("Add a highlight annotation.");
                    }
                }
            }
            {
                // Add underline annotation.
                Underline underline = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Underline, new RectF(100, 450, 200, 550)))
                using (underline = new Underline(annot))
                using (QuadPoints quad_points = new QuadPoints())
                using (quad_points.first = new foxit.common.fxcrt.PointF(110, 500))
                using (quad_points.second = new foxit.common.fxcrt.PointF(190, 500))
                using (quad_points.third = new foxit.common.fxcrt.PointF(110, 480))
                using (quad_points.fourth = new foxit.common.fxcrt.PointF(190, 480))
                using (QuadPointsArray quad_points_array = new QuadPointsArray())
                {
                    quad_points_array.Add(quad_points);
                    //This flag is used for printing annotations.
                    underline.SetFlags(4);
                    underline.SetQuadPoints(quad_points_array);
                    underline.SetSubject("Underline");
                    underline.SetTitle("Foxit SDK");
                    underline.SetCreationDateTime(GetLocalDateTime());
                    underline.SetModifiedDateTime(GetLocalDateTime());
                    underline.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    underline.ResetAppearanceStream();
                    Console.WriteLine("Add a underline annotation.");
                }
            }
            {
                // Add squiggly annotation.
                Squiggly squiggly = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Squiggly, new RectF(200, 450, 300, 550)))
                using (squiggly = new Squiggly(annot))
                {
                    squiggly.SetIntent("Squiggly");
                    //This flag is used for printing annotations.
                    squiggly.SetFlags(4);
                    using (QuadPoints quad_points = new QuadPoints())
                    using (quad_points.first = new foxit.common.fxcrt.PointF(210, 500))
                    using (quad_points.second = new foxit.common.fxcrt.PointF(290, 500))
                    using (quad_points.third = new foxit.common.fxcrt.PointF(210, 480))
                    using (quad_points.fourth = new foxit.common.fxcrt.PointF(290, 480))
                    using (QuadPointsArray quad_points_array = new QuadPointsArray())
                    {
                        quad_points_array.Add(quad_points);
                        squiggly.SetQuadPoints(quad_points_array);
                        squiggly.SetSubject("Squiggly");
                        squiggly.SetTitle("Foxit SDK");
                        squiggly.SetCreationDateTime(GetLocalDateTime());
                        squiggly.SetModifiedDateTime(GetLocalDateTime());
                        squiggly.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        squiggly.ResetAppearanceStream();
                        Console.WriteLine("Add a squiggly annotation.");
                    }
                }
            }
            {
                // Add strikeout annotation.
                StrikeOut strikeout = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_StrikeOut, new RectF(300, 450, 400, 550)))
                using (strikeout = new StrikeOut(annot))
                using (QuadPoints quad_points = new QuadPoints())
                using (quad_points.first = new foxit.common.fxcrt.PointF(310, 500))
                using (quad_points.second = new foxit.common.fxcrt.PointF(390, 500))
                using (quad_points.third = new foxit.common.fxcrt.PointF(310, 480))
                using (quad_points.fourth = new foxit.common.fxcrt.PointF(390, 480))
                using (QuadPointsArray quad_points_array = new QuadPointsArray())
                {
                    quad_points_array.Add(quad_points);
                    //This flag is used for printing annotations.
                    strikeout.SetFlags(4);
                    strikeout.SetQuadPoints(quad_points_array);
                    strikeout.SetSubject("StrikeOut");
                    strikeout.SetTitle("Foxit SDK");
                    strikeout.SetCreationDateTime(GetLocalDateTime());
                    strikeout.SetModifiedDateTime(GetLocalDateTime());
                    strikeout.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    strikeout.ResetAppearanceStream();
                    Console.WriteLine("Add a strikeout annotation.");
                }
            }
            {
                // Add caret annotation.
                Caret caret = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Caret, new RectF(400, 450, 420, 470)))
                using (caret = new Caret(annot))
                {
                    //This flag is used for printing annotations.
                    caret.SetFlags(4);
                    caret.SetInnerRect(new RectF(410, 450, 430, 470));
                    caret.SetContent("Caret annotation");
                    caret.SetSubject("Caret");
                    caret.SetTitle("Foxit SDK");
                    caret.SetCreationDateTime(GetLocalDateTime());
                    caret.SetModifiedDateTime(GetLocalDateTime());
                    caret.SetUniqueID(RandomUID());
                    // Appearance should be reset.
                    caret.ResetAppearanceStream();
                    Console.WriteLine("Add a caret annotation.");
                }
            }

            {
                // Add note annotation
                Note note = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Note, new RectF(10, 350, 50, 400)))
                using (note = new Note(annot))
                {
                    //This flag is used for printing annotations.
                    note.SetFlags(4);
                    note.SetIconName("Comment");
                    note.SetSubject("Note");
                    note.SetTitle("Foxit SDK");
                    note.SetContent("Note annotation.");
                    note.SetCreationDateTime(GetLocalDateTime());
                    note.SetModifiedDateTime(GetLocalDateTime());
                    note.SetUniqueID(RandomUID());

                    // Add popup to note annotation
                    Popup popup = null;
                    using (annot = page.AddAnnot(Annot.Type.e_Popup, new RectF(300, 450, 500, 550)))
                    using (popup = new Popup(annot))
                    {
                        popup.SetBorderColor(0x00FF00);
                        popup.SetOpenStatus(false);
                        popup.SetModifiedDateTime(GetLocalDateTime());
                        note.SetPopup(popup);

                        // Add reply annotation to note annotation
                        using (Note reply = note.AddReply())
                        {
                            reply.SetContent("reply");
                            reply.SetModifiedDateTime(GetLocalDateTime());
                            reply.SetTitle("Foxit SDK");
                            reply.SetUniqueID(RandomUID());

                            // Add state annotation to note annotation
                            using (Note state = note.AddStateAnnot("Foxit SDK", Markup.StateModel.e_StateModelReview, Markup.State.e_StateAccepted))
                            {
                                state.SetContent("Accepted set by Foxit SDK");
                                state.SetUniqueID(RandomUID());
                                // Appearance should be reset.
                                note.ResetAppearanceStream();
                                Console.WriteLine("Add a note annotation.");
                            }
                        }
                    }
                }
            }

            {
                // Add ink annotation
                Ink ink = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Ink, new RectF(100, 350, 200, 450)))
                using (ink = new Ink(annot))
                using (foxit.common.Path inklist = new foxit.common.Path())
                {
                    float width = 100;
                    float height = 100;
                    float out_width = (float)(Math.Min(width, height) * 2 / 3.0f);
                    float inner_width = (float)(out_width * Math.Sin(18.0f / 180.0f * 3.14f) / Math.Sin(36.0f / 180.0f * 3.14f));
                    using (foxit.common.fxcrt.PointF center = new foxit.common.fxcrt.PointF(150, 400))
                    {

                        float x = out_width;
                        float y = 0;
                        inklist.MoveTo(new foxit.common.fxcrt.PointF(center.x + x, center.y + y));
                        for (int i = 0; i < 5; i++)
                        {
                            x = (float)(out_width * Math.Cos(72.0f * i / 180.0f * 3.14f));
                            y = (float)(out_width * Math.Sin(72.0f * i / 180.0f * 3.14f));
                            inklist.LineTo(new foxit.common.fxcrt.PointF(center.x + x, center.y + y));

                            x = (float)(inner_width * Math.Cos((72.0f * i + 36) / 180.0f * 3.14f));
                            y = (float)(inner_width * Math.Sin((72.0f * i + 36) / 180.0f * 3.14f));
                            inklist.LineTo(new foxit.common.fxcrt.PointF(center.x + x, center.y + y));
                        }
                        inklist.LineTo(new foxit.common.fxcrt.PointF(center.x + out_width, center.y + 0));
                        inklist.CloseFigure();
                        //This flag is used for printing annotations.
                        ink.SetFlags(4);
                        ink.SetInkList(inklist);
                        ink.SetSubject("Ink");
                        ink.SetTitle("Foxit SDK");
                        ink.SetContent("Note annotation.");
                        ink.SetCreationDateTime(GetLocalDateTime());
                        ink.SetModifiedDateTime(GetLocalDateTime());
                        ink.SetUniqueID(RandomUID());
                        // Appearance should be reset.
                        ink.ResetAppearanceStream();
                        Console.WriteLine("Add an ink annotation.");
                    }
                }
            }

            {
                // Add file attachment annotation
                String pdf_file = input_path + "AboutFoxit.pdf";
                FileAttachment file_attachment = null;
                Annot annot = null;
                PDFDoc doc = null;
                using (annot = page.AddAnnot(Annot.Type.e_FileAttachment, new RectF(280, 350, 300, 380)))
                using (file_attachment = new FileAttachment(annot))
                {
                    //This flag is used for printing annotations.
                    file_attachment.SetFlags(4);
                    file_attachment.SetIconName("Graph");
                    foxit.pdf.FileSpec file_spec = null;
                    using (doc = page.GetDocument())
                    using (file_spec = new foxit.pdf.FileSpec(doc))
                    {
                        file_spec.SetFileName("attachment.pdf");
                        file_spec.SetCreationDateTime(GetLocalDateTime());
                        file_spec.SetDescription("The original file");
                        file_spec.SetModifiedDateTime(GetLocalDateTime());
                        file_spec.Embed(pdf_file);
                        file_attachment.SetFileSpec(file_spec);
                        file_attachment.SetSubject("File Attachment");
                        file_attachment.SetTitle("Foxit SDK");
                        // Appearance should be reset.
                        file_attachment.ResetAppearanceStream();
                        Console.WriteLine("Add an attachment annotation.");
                    }
                }
            }

            {
                // Add link annotation
                Link link = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_Link, new RectF(350, 350, 380, 400)))
                using (link = new Link(annot))
                using (PDFDoc doc = page.GetDocument())
                {
                    foxit.pdf.actions.Action action = null;
                    link.SetHighlightingMode(Annot.HighlightingMode.e_HighlightingPush);
                    //This flag is used for printing annotations.
                    link.SetFlags(4);
                    // Add action for link annotation
                    URIAction uriaction = null;
                    using (action = foxit.pdf.actions.Action.Create(doc, foxit.pdf.actions.Action.Type.e_TypeURI))
                    using (uriaction = new URIAction(action))
                    {
                        uriaction.SetTrackPositionFlag(true);
                        uriaction.SetURI("www.foxitsoftware.com");
                        link.SetAction(uriaction);
                        // Appearance should be reset.
                        link.ResetAppearanceStream();
                        Console.WriteLine("Add a link annotation.");
                    }
                }
            }
            {
                // Set icon provider for annotation to Foxit PDF SDK.
                IconProvider icon_provider = new IconProvider("../input_files/Stamps");
                icon_provider.SetUseDynamicStamp(false);
                Library.SetAnnotIconProviderCallback(icon_provider);

                // Add common stamp annotation.
                Library.SetActionCallback(null);
                Stamp static_stamp = null;
                Annot annot = null;

                using (annot = page.AddAnnot(Annot.Type.e_Stamp, new RectF(110, 150, 200, 250)))
                using (static_stamp = new Stamp(annot))
                {
                    //This flag is used for printing annotations.
                    static_stamp.SetFlags(4);
                    static_stamp.SetIconName("Approved");
                    // Appearance should be reset.
                    static_stamp.ResetAppearanceStream();

                    
                   // using (action_event = new ActionEvent(page.GetDocument()))
                    {
                        // Add dynamic stamp annotation.
                        Library.SetActionCallback(action_callback);
                        icon_provider.SetUseDynamicStamp(true);
                        Stamp dynamic_stamp = null;
                        using (annot = page.AddAnnot(Annot.Type.e_Stamp, new RectF(10, 150, 100, 250)))
                        using (dynamic_stamp = new Stamp(annot))
                        {
                            //This flag is used for printing annotations.
                            dynamic_stamp.SetFlags(4);
                            dynamic_stamp.SetIconName("Approved");
                            // Appearance should be reset.
                            dynamic_stamp.ResetAppearanceStream();
                            Console.WriteLine("Add stamp annotations.");
                        }
                    }
                    
                }
            }
            
            {
                // Add freetext annotation with richtext, as type writer.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(10, 50, 200, 100)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)(DefaultAppearance.DefAPFlags.e_FlagFont | DefaultAppearance.DefAPFlags.e_FlagFontSize | DefaultAppearance.DefAPFlags.e_FlagTextColor);
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelvetica))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        freetext.SetDefaultAppearance(default_ap);
                        freetext.SetIntent("FreeTextTypewriter");
                        freetext.SetContent("A typewriter annotation");
                        freetext.SetSubject("FreeTextTypewriter");
                        freetext.SetTitle("Foxit SDK");
                        freetext.SetCreationDateTime(GetLocalDateTime());
                        freetext.SetModifiedDateTime(GetLocalDateTime());
                        freetext.SetUniqueID(RandomUID());
                        using (RichTextStyle richtext_style = new RichTextStyle())
                        {
                            {
                                String font_name = "Times New Roman";
                                if (Environment.OSVersion.Platform == PlatformID.Unix)
                                    font_name = "FreeMono";
                                using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                {
                                    richtext_style.text_color = 0xFF0000;
                                    richtext_style.text_size = 10;
                                    freetext.AddRichText("Typewriter annotation ", richtext_style);

                                    richtext_style.text_color = 0x00FF00;
                                    richtext_style.is_underline = true;
                                    freetext.AddRichText("1-underline ", richtext_style);
                                }
                            }
                            {
                                String font_name = "Calibri";
                                if (Environment.OSVersion.Platform == PlatformID.Unix)
                                    font_name = "FreeSerif";
                                using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                {
                                    richtext_style.text_color = 0x0000FF;
                                    richtext_style.is_underline = false;
                                    richtext_style.is_strikethrough = true;
                                    int richtext_count = freetext.GetRichTextCount();
                                    freetext.InsertRichText(richtext_count - 1, "2_strikethrough ", richtext_style);
                                }
                            }
                        }
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        // Appearance should be reset.
                        freetext.ResetAppearanceStream();
                        Console.WriteLine("Add a typewriter freetext annotation with richtext.");
                    }
                }
            }

            {
                // Add freetext annotation with richtext, as call-out.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(300, 50, 400, 100)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)DefaultAppearance.DefAPFlags.e_FlagFont | (int)DefaultAppearance.DefAPFlags.e_FlagFontSize | (int)DefaultAppearance.DefAPFlags.e_FlagTextColor;
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelveticaB))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        // Set default appearance for form.
                        freetext.SetDefaultAppearance(default_ap);

                        freetext.SetIntent("FreeTextCallout");
                        using (PointFArray callout_points = new PointFArray())
                        using (foxit.common.fxcrt.PointF point1 = new foxit.common.fxcrt.PointF(250, 60))
                        using (foxit.common.fxcrt.PointF point2 = new foxit.common.fxcrt.PointF(280, 80))
                        using (foxit.common.fxcrt.PointF point3 = new foxit.common.fxcrt.PointF(300, 80))
                        {
                            callout_points.Add(point1);
                            callout_points.Add(point2);
                            callout_points.Add(point3);

                            freetext.SetCalloutLinePoints(callout_points);
                            freetext.SetCalloutLineEndingStyle(Markup.EndingStyle.e_EndingStyleOpenArrow);
                            freetext.SetContent("A callout annotation.");
                            freetext.SetSubject("FreeTextCallout");
                            freetext.SetTitle("Foxit SDK");
                            freetext.SetCreationDateTime(GetLocalDateTime());
                            freetext.SetModifiedDateTime(GetLocalDateTime());
                            freetext.SetUniqueID(RandomUID());
                            using (RichTextStyle richtext_style = new RichTextStyle())
                            {
                                {
                                    String font_name = "Times New Roman";
                                    if (Environment.OSVersion.Platform == PlatformID.Unix)
                                        font_name = "FreeMono";
                                    using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                    {
                                        richtext_style.text_color = 0xFF0000;
                                        richtext_style.text_size = 10;
                                        freetext.AddRichText("Callout annotation ", richtext_style);

                                        richtext_style.text_color = 0x00FF00;
                                        richtext_style.is_underline = true;
                                        freetext.AddRichText("1-underline ", richtext_style);
                                    }
                                }
                                {
                                    String font_name = "Calibri";
                                    if (Environment.OSVersion.Platform == PlatformID.Unix)
                                        font_name = "FreeSerif";
                                    using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                    {
                                        richtext_style.text_color = 0x0000FF;
                                        richtext_style.is_underline = false;
                                        richtext_style.is_strikethrough = true;
                                        int richtext_count = freetext.GetRichTextCount();
                                        freetext.InsertRichText(richtext_count - 1, "2_strikethrough ", richtext_style);
                                    }
                                }
                            }
                            // Appearance should be reset.
                            freetext.ResetAppearanceStream();
                            Console.WriteLine("Add a callout freetext annotation with richtext.");
                        }
                    }
                }
            }

            {
                // Add freetext annotation with richtext, as text box.
                FreeText freetext = null;
                Annot annot = null;
                using (annot = page.AddAnnot(Annot.Type.e_FreeText, new RectF(450, 50, 550, 100)))
                using (freetext = new FreeText(annot))
                // Set default appearance
                using (DefaultAppearance default_ap = new DefaultAppearance())
                {
                    default_ap.flags = (int)DefaultAppearance.DefAPFlags.e_FlagFont | (int)DefaultAppearance.DefAPFlags.e_FlagFontSize | (int)DefaultAppearance.DefAPFlags.e_FlagTextColor;
                    using (default_ap.font = new foxit.common.Font(foxit.common.Font.StandardID.e_StdIDHelveticaI))
                    {
                        default_ap.text_size = 12.0f;
                        default_ap.text_color = 0x000000;
                        //This flag is used for printing annotations.
                        freetext.SetFlags(4);
                        freetext.SetDefaultAppearance(default_ap);
                        freetext.SetContent("A text box annotation.");
                        freetext.SetSubject("Textbox");
                        freetext.SetTitle("Foxit SDK");
                        freetext.SetCreationDateTime(GetLocalDateTime());
                        freetext.SetModifiedDateTime(GetLocalDateTime());
                        freetext.SetUniqueID(RandomUID());
                        using (RichTextStyle richtext_style = new RichTextStyle())
                        {
                            {
                                String font_name = "Times New Roman";
                                if (Environment.OSVersion.Platform == PlatformID.Unix)
                                    font_name = "FreeMono";
                                using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                {
                                    richtext_style.text_color = 0xFF0000;
                                    richtext_style.text_size = 10;
                                    freetext.AddRichText("Textbox annotation ", richtext_style);

                                    richtext_style.text_color = 0x00FF00;
                                    richtext_style.is_underline = true;
                                    freetext.AddRichText("1-underline ", richtext_style);
                                }
                            }
                            {
                                String font_name = "Calibri";
                                if (Environment.OSVersion.Platform == PlatformID.Unix)
                                    font_name = "FreeSerif";
                                using (richtext_style.font = new foxit.common.Font(font_name, 0, foxit.common.Font.Charset.e_CharsetANSI, 0))
                                {
                                    richtext_style.text_color = 0x0000FF;
                                    richtext_style.is_underline = false;
                                    richtext_style.is_strikethrough = true;
                                    int richtext_count = freetext.GetRichTextCount();
                                    freetext.InsertRichText(richtext_count - 1, "2_strikethrough ", richtext_style);
                                }
                            }
                        }
                        // Appearance should be reset.
                        freetext.ResetAppearanceStream();
                        Console.WriteLine("Add a text box freetext annotation with richtext.");
                    }
                }
            }

            {
                //Add a screen annotation
                Screen screen = null;
                Annot annot = null;
                foxit.common.Image image = null;
                Rendition rendition = null;
                RenditionAction rendition_action = null;
                FileSpec video_filespec = null;
                foxit.pdf.actions.Action action = null;
                BorderInfo borderInfo = null;
                PDFDoc doc = null;
                using(doc = page.GetDocument())
                using (annot = page.AddAnnot(Annot.Type.e_Screen, new RectF(300, 150, 400, 200)))
                using (image = new foxit.common.Image(input_path + "FoxitLogo.jpg"))
                using (rendition = new Rendition(doc, null))
                using (action = foxit.pdf.actions.Action.Create(doc, foxit.pdf.actions.Action.Type.e_TypeRendition))
                using (rendition_action = new RenditionAction(action))
                using (video_filespec = new FileSpec(doc))
                using (borderInfo = new BorderInfo(2, BorderInfo.Style.e_Solid, 0, 0, new FloatArray()))
                using (screen = new Screen(annot))
                {
                  //This flag is used for printing annotations.
                  screen.SetFlags(4);
                  screen.SetTitle("Foxit SDK");
                  screen.SetUniqueID(RandomUID());
                  screen.SetBorderColor(0x0000FF);
                  screen.SetBorderInfo(borderInfo);
                  screen.SetImage(image, 0, 1);

                  // Prepare rendition action
                  rendition_action.SetOperationType(RenditionAction.OperationType.e_OpTypeAssociate);
                  rendition_action.SetScreenAnnot(screen);

                  // Prepare rendition
                  rendition.SetRenditionName("screen for rendition");
                  rendition.SetMediaClipName("ytb210-Mopa.mp4");
                  rendition.SetPermission(Rendition.MediaPermission.e_MediaPermTempAccess);

                  String video_file_path = input_path + "ytb210-Mopa.mp4";
                  video_filespec.SetFileName("ytb210-Mopa.mp4");
                  video_filespec.Embed(video_file_path);
                  rendition.SetMediaClipFile(video_filespec);
                  rendition.SetMediaClipContentType("video/mp4");
                  rendition_action.InsertRendition(rendition, 0);
                  screen.SetAction(rendition_action);

                  // Appearance should be reset.
                  screen.ResetAppearanceStream();
                  Console.WriteLine("Add a screen annotation.");
                }
            }

        }

        static void AddAnnotsWithLowLevelAPI(PDFPage page)
        {
            {
                // Add line annotation
                PDFDictionary annot_dict = PDFDictionary.Create();
                annot_dict.SetAtName("Type", "Annot");
                annot_dict.SetAtName("Subtype", "Line");
                annot_dict.SetAtName("IT", "LineArrow");
                annot_dict.SetAtInteger("F", 4);
                annot_dict.SetAtString("Contents", "A line arrow annotation.");
                annot_dict.SetAtString("T", "Foxit SDK");
                annot_dict.SetAtString("Subj", "Arrow");
                annot_dict.SetAtString("NM", RandomUID());
                annot_dict.SetAtDateTime("CreationDate", GetLocalDateTime());
                annot_dict.SetAtDateTime("M", GetLocalDateTime());
                annot_dict.SetAtRect("Rect", new RectF(0, 650, 100, 750));
                PDFArray coords_array = PDFArray.Create();
                coords_array.AddFloat(20);
                coords_array.AddFloat(670);
                coords_array.AddFloat(80);
                coords_array.AddFloat(730);
                annot_dict.SetAt("L", coords_array);

                PDFArray line_style = PDFArray.Create();
                line_style.AddName("None");
                line_style.AddName("OpenArrow");
                annot_dict.SetAt("LE", line_style);
                PDFDictionary border_dict = PDFDictionary.Create();
                border_dict.SetAtFloat("W", 2.0f);
                border_dict.SetAtName("S", "S");
                border_dict.SetAtName("Type", "Border");
                annot_dict.SetAt("BS", border_dict);
                PDFArray color_array = PDFArray.Create();
                color_array.AddFloat(1);
                color_array.AddFloat(1);
                color_array.AddFloat(0);
                annot_dict.SetAt("C", color_array);
                Annot annot = null;
                using (annot = page.AddAnnot(annot_dict))
                {
                    annot.ResetAppearanceStream();
                }
                Console.WriteLine("Add a line annotation by lower level API.");
            }

            {
                // Add line annotation with caption
                PDFDictionary annot_dict =  PDFDictionary.Create();
                annot_dict.SetAtName("Type", "Annot");
                annot_dict.SetAtName("Subtype", "Line");
                annot_dict.SetAtName("IT", "LineArrow");
                annot_dict.SetAtInteger("F", 4);
                annot_dict.SetAtString("Contents", "A common line.");
                annot_dict.SetAtString("T", "Foxit SDK");
                annot_dict.SetAtString("Subj", "Line");
                annot_dict.SetAtString("NM", RandomUID());
                annot_dict.SetAtDateTime("CreationDate", GetLocalDateTime());
                annot_dict.SetAtDateTime("M", GetLocalDateTime());
                annot_dict.SetAtRect("Rect", new RectF(0, 650, 100, 750));
                annot_dict.SetAtBoolean("Cap", true);

                PDFArray caption_offset =  PDFArray.Create();
                caption_offset.AddFloat(0);
                caption_offset.AddFloat(5);
                annot_dict.SetAt("CO", caption_offset);
                PDFArray coords_array =  PDFArray.Create();
                coords_array.AddFloat(40);
                coords_array.AddFloat(670);
                coords_array.AddFloat(100);
                coords_array.AddFloat(730);
                annot_dict.SetAt("L", coords_array);
                PDFArray line_style =  PDFArray.Create();
                line_style.AddName("Square");
                line_style.AddName("OpenArrow");
                annot_dict.SetAt("LE", line_style);
                PDFDictionary border_dict =  PDFDictionary.Create();
                border_dict.SetAtFloat("W", 2.0f);
                border_dict.SetAtName("S", "S");
                border_dict.SetAtName("Type", "Border");
                annot_dict.SetAt("BS", border_dict);
                PDFArray color_array =  PDFArray.Create();
                color_array.AddFloat(0);
                color_array.AddFloat(1);
                color_array.AddFloat(0);
                annot_dict.SetAt("C", color_array);
                Annot annot = null;
                using (annot = page.AddAnnot(annot_dict))
                {
                    annot.ResetAppearanceStream();
                }
                Console.WriteLine("Add a line annotation with caption by lower level API.");
            }

            {
                // Add circle annotation
                PDFDictionary annot_dict = PDFDictionary.Create();
                annot_dict.SetAtName("Type", "Annot");
                annot_dict.SetAtName("Subtype", "Circle");
                annot_dict.SetAtInteger("F", 4);
                annot_dict.SetAtString("T", "Foxit SDK");
                annot_dict.SetAtString("Subj", "Circle");
                annot_dict.SetAtString("NM", RandomUID());
                annot_dict.SetAtDateTime("CreationDate", GetLocalDateTime());
                annot_dict.SetAtDateTime("M", GetLocalDateTime());
                annot_dict.SetAtRect("Rect", new RectF(120, 650, 180, 750));

                PDFDictionary border_dict = PDFDictionary.Create();
                border_dict.SetAtFloat("W", 2.0f);
                border_dict.SetAtName("S", "S");
                border_dict.SetAtName("Type", "Border");
                annot_dict.SetAt("BS", border_dict);
                PDFArray color_array = PDFArray.Create();
                color_array.AddFloat(0);
                color_array.AddFloat(1);
                color_array.AddFloat(0);
                annot_dict.SetAt("C", color_array);
                Annot annot = null;
                using (annot = page.AddAnnot(annot_dict))
                {
                    annot.ResetAppearanceStream();
                }
                Console.WriteLine("Add a circle annotation by lower level API.");
            }

            {
                // Add square annotation
                PDFDictionary annot_dict = PDFDictionary.Create();
                annot_dict.SetAtName("Type", "Annot");
                annot_dict.SetAtName("Subtype", "Square");
                annot_dict.SetAtInteger("F", 4);
                annot_dict.SetAtString("T", "Foxit SDK");
                annot_dict.SetAtString("Subj", "Square");
                annot_dict.SetAtString("NM", RandomUID());
                annot_dict.SetAtDateTime("CreationDate", GetLocalDateTime());
                annot_dict.SetAtDateTime("M", GetLocalDateTime());
                annot_dict.SetAtRect("Rect", new RectF(200, 650, 300, 750));

                PDFDictionary border_dict = PDFDictionary.Create();
                border_dict.SetAtFloat("W", 2.0f);
                border_dict.SetAtName("S", "S");
                border_dict.SetAtName("Type", "Border");
                annot_dict.SetAt("BS", border_dict);
                PDFArray interior_color_array = PDFArray.Create();
                interior_color_array.AddFloat(1);
                interior_color_array.AddFloat(1);
                interior_color_array.AddFloat(0);
                annot_dict.SetAt("IC", interior_color_array);
                PDFArray color_array = PDFArray.Create();
                color_array.AddFloat(0);
                color_array.AddFloat(1);
                color_array.AddFloat(0);
                annot_dict.SetAt("C", color_array);
                Annot annot = null;
                using (annot = page.AddAnnot(annot_dict))
                {
                    annot.ResetAppearanceStream();
                }
                Console.WriteLine("Add a square annotation by lower level API.");
            }
        }

        static bool SaveSoundToFile(Sound sound, string file_path)
        {
            if (sound.IsEmpty())
            {
                return false;
            }
            FileStream sound_file_stream = new FileStream(file_path, FileMode.Create);
            BinaryWriter file_writer = new BinaryWriter(sound_file_stream);

            PDFStream sound_stream = sound.GetSoundStream();
            int stream_size = sound_stream.GetDataSize(false);
            IntPtr data = Marshal.AllocHGlobal(stream_size);
            sound_stream.GetData(false, (uint)stream_size, data);
            short bit = (short)sound.GetBits();
            int riff_size = stream_size + 36;

            char[] chunk_riff = { 'R', 'I', 'F', 'F' };
            char[] chunk_type = { 'W', 'A', 'V', 'E' };
            char[] chunk_fmt = { 'f', 'm', 't', ' ' };
            char[] chunk_data = { 'd', 'a', 't', 'a' };

            int chunk_size = 16;
            short format = 1;
            short channel_count = (short)sound.GetChannelCount();
            int rate = (int)sound.GetSamplingRate();
            int byte_per_sec = rate * channel_count * bit / 8;
            short block_align = (short)(bit * channel_count / 8);

            //write file header:
            //header -- RIFF 
            file_writer.Write(chunk_riff);
            file_writer.Write(riff_size);
            file_writer.Write(chunk_type);

            //header -- WAVE 
            file_writer.Write(chunk_fmt);
            file_writer.Write(chunk_size);
            file_writer.Write(format);
            file_writer.Write(channel_count);
            file_writer.Write(rate);
            file_writer.Write(byte_per_sec);
            file_writer.Write(block_align);
            file_writer.Write(bit);

            //header -- data  
            file_writer.Write(chunk_data);
            file_writer.Write(stream_size);

            //write file data:
            Sound.SampleEncodingFormat encoding_format = sound.GetSampleEncodingFormat();
            switch (encoding_format)
            {
                case Sound.SampleEncodingFormat.e_SampleEncodingFormatALaw:
                    break;
                case Sound.SampleEncodingFormat.e_SampleEncodingFormatMuLaw:
                    break;
                case Sound.SampleEncodingFormat.e_SampleEncodingFormatSigned:
                    {
                        byte[] buffer = new byte[stream_size];
                        Marshal.Copy(data, buffer, 0, stream_size);
                        byte[] buffer_signed = new byte[stream_size + 1];
                        int j = 0, k = 0;
                        for (int i = 0; i < stream_size; i += 2)
                        {
                            byte low = buffer[j++];
                            byte high;
                            if (j == stream_size)
                            {
                                high = 0;
                            }
                            else
                            {
                                high = buffer[j++];
                            }
                            buffer_signed[k++] = high;
                            buffer_signed[k++] = low;
                        }
                        file_writer.Write(buffer_signed, 0, stream_size + 1);
                    }
                    break;
                case Sound.SampleEncodingFormat.e_SampleEncodingFormatRaw:
                default:
                    {
                        byte[] buffer = new byte[stream_size];
                        Marshal.Copy(data, buffer, 0, stream_size);
                        file_writer.Write(buffer, 0, stream_size);
                    }
                    break;
            }

            file_writer.Close();
            sound_file_stream.Close();
            file_writer = null;
            sound_file_stream = null;
            Marshal.FreeHGlobal(data);
            return true;
        }

        static Annot GetAnnotWithType(PDFPage pdf_page, Annot.Type annot_type, int annot_index_with_type)
        {
            Annot ret_annot = null;
            if (pdf_page.IsEmpty() || (int)annot_type < -1) return ret_annot;
            int annot_count = pdf_page.GetAnnotCount();
            int spec_annot_index = -1;
            for (int i = 0; i < annot_count; i++)
            {
                Annot annot_i = pdf_page.GetAnnot(i);
                int cmp_index = -1;

                if (-1 == (int)annot_type)
                {
                    cmp_index = i;
                }
                else if (annot_i.GetType() == annot_type)
                {
                    spec_annot_index++;
                    cmp_index = spec_annot_index;
                }
                if (cmp_index == annot_index_with_type)
                {
                    ret_annot = annot_i;
                    break;
                }
            }
            return ret_annot;
        }

        static Sound GetSoundAnnot(String input_pdf_path, int page_index)
        {
            Sound sound = null;
            using (PDFDoc doc = new PDFDoc(input_pdf_path))
            {
                doc.Load(null);
                using (PDFPage pdf_page = doc.GetPage(page_index))
                {
                    if (pdf_page.IsEmpty())
                    {
                        return sound;
                    }

                    using (Annot annot = GetAnnotWithType(pdf_page, Annot.Type.e_Sound, 0))
                    {
                        if (annot.IsEmpty())
                        {
                            return sound;
                        }
                        if (annot.GetType() != Annot.Type.e_Sound)
                        {
                            return sound;
                        }
                        sound = new Sound(annot);
                    }

                }
            }

            return sound;
        }
        static void Main(String[] args)
        {
            string input_path = "../input_files/";

            System.IO.Directory.CreateDirectory(output_path);
            // Initialize library
            string sn = "Rew1vB0TqoMIxX444UcpScARWdhgJpsJfzmyMLR32a0+EgrCjp2NaQ==";
            string key = "8f3g1sFttW8NAgfSNv+BvaJWy4Pp8flcm7ncNDkdvCCO4JwUFbGLyZdujReMaiplbYJwwxam3lr7uHtQaEf0xTSu8j2ZBdrZ8FS4OQkEUjOI9UEGb3Ic0GqmlP9T9OnSItOYqoZZA/OnYg5EaVP+c/ha32nUquOk+5riEdhYgINAZDdgJkPc+YSWsrfixOIROf6t34j3eRcyFnOY0MS7tSXi1AEPE0VZdyu+5bfmBSGvLI+WR5lQ+oOQR5hRGwqf990WEdBelNO7dxhZELVhEZ+/L60PpDf5y9A8qmrY6PiEU8nhqIyLpks0BxeIsYyZ3Cr82jjfbItPGyEARsIVzluBSgVMD4oGjojz8T6wGDEXUbmZH/pra94XAs8wZ28mzbmIEppWnhBqX0c6Ov8iXCfFfUZr4KNuPxMEgk4VOYTMOd70GEjGnylivw18hbn7ZpkWh2Zql+uU2HejvOgn+WHvT0HF9NhK0Xb5vH8aFkgBP92PJx8obIbxBVeeExczxvsqWufuPdXS2sPNIgMYZ2TtvqVVsiUToeGB2FQo09fzZOSH5Vi18u/siyvC3FmjeMf4+OYWPuDPNCcrb21NgcHam7XI8AAoGLTGtLLWR+fxynbBBcg2d2ZPcZ5CMFIfOBHRWCkcA0sDT3cl9nsBppHNJze/jVxHy+lREeQEA/etSIgohTGAWW3ZlpibRXqMxlmVWEPifCubbWTzQ6U54mRMpW2UghH3gvCNFNgdday3Av7EtlIJOdUuiMq3zmmd5J4Jt4C82CKnVewA0DtZ4EEtwRG9IYuLrfpuZlnjBAtoeXRV1lqUZ6BcCe0E3m9jO28sGkALuIeJQ74XG7X8lMC7lMWWQYiYD7D6G9QT6X3qV4vXJwNKRKpYc/rI+amEawTSnDYAMEaYPwtZ0rb/7BL+atsZZaI+ncebdfVfjDJZbCZAc+JnkuNlUn2xrNRuObw8h/G0lm2pNOEJ10S8R4+yplo5B1QmC2dCDhaTaW67QJPqnJPKbVmjw7i6KGBi+CDP3JnAKlOX/YUu8uk56JfeQUuGcQg/KaBMGctnchH2n1i3+oGbibhurQj22+OO66Q6mijKoCRP/QJm5WTGcO4c0iVX0B8dIlai/uv/pGU8Wps9MxysH5ViVIj56LWKuNfy1FNO9+wx4iHYnUxfW0Iccq3YJYAlOBkMv8VZIJl9aTEEFJ626LJEw/UbEBdR9CdlwnylPf4RuNW/lcGYMgq3xNVpp/bzYKwZivvQOFgMdX1tv8D33SHvAm3zrRCU+v94BJXnBi9k25fnKsc705IMwv+I6bueXA+mDnagj1oTqsWXZ0WnPAYI3WUO7sBf7XUH230wfYXnTSVhujJxiEP/2oWqi2813gtQkKwz9N2p6yT8Vsh3+BaAwwDvtOZMJKUFcabTBSL6NoouzmzwItJ4mIboT6KXaef66rs8jCU=";
            ErrorCode error_code = Library.Initialize(sn, key);
            if (error_code != ErrorCode.e_ErrSuccess)
                Console.WriteLine("Library Initialize Error: {0}\n", error_code);

            try
            {
                String input_file = input_path + "annotation_input.pdf";
                // Load a document
                using (PDFDoc doc = new PDFDoc(input_file))
                {
                    ActionEvent action_event = new ActionEvent(doc);
                    error_code = doc.Load(null);
                    if (error_code != ErrorCode.e_ErrSuccess)
                    {
                        Console.WriteLine("[Failed] Cannot load PDF document: " + input_file + ".\r\nError Code: " + error_code + "\r\n");
                        return;
                    }

                    // Get first page with index 0
                    using (PDFPage page = doc.GetPage(0))
                    {
                        AddAnnotations(page, action_event);
                        // Save PDF file
                        String newPdf = output_path + "annotation.pdf";
                        doc.SaveAs(newPdf, (int)PDFDoc.SaveFlags.e_SaveFlagNoOriginal);
                    }
                }
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            try
            {
                String input_file = input_path + "annotation_input.pdf";
                // Load a document
                using (PDFDoc doc = new PDFDoc(input_file))
                {
                    error_code = doc.Load(null);
                    if (error_code != ErrorCode.e_ErrSuccess)
                    {
                        Console.WriteLine("[Failed] Cannot load PDF document: " + input_file + ".\r\nError Code: " + error_code + "\r\n");
                        return;
                    }

                    // Get first page with index 0
                    using (PDFPage page = doc.GetPage(0))
                    {
                        AddAnnotsWithLowLevelAPI(page);
                        // Save PDF file
                        String newPdf = output_path + "annotation_lower_level_API.pdf";
                        doc.SaveAs(newPdf, (int)PDFDoc.SaveFlags.e_SaveFlagNoOriginal);
                    }
                }
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            //save sound to file:
            try
            {
                string output_sound_file = output_path + "sound.wav";
                String input_sound_pdf_file = input_path + "sound.pdf";
                using (Sound sound = GetSoundAnnot(input_sound_pdf_file, 0))
                {
                    if (SaveSoundToFile(sound, output_sound_file))
                    {
                        Console.WriteLine("Save sound annotation to file, saved file path:" + output_sound_file + " \r\n");
                    }
                }
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Library.Release();
        }
    }
}
