// 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 create a PDF document,
// insert the text path and image objects into the created PDF document, copy shading objects,
// and save the file with inserted graphics objects.

using System;
using System.Collections.Generic;
using System.IO;

using foxit.common;
using foxit.pdf;
using foxit.pdf.graphics;
using foxit.common.fxcrt;

namespace graphics_objectsCS
{
    class graphics_objects
    {
        const string input_path = "../input_files/";
        const string output_path = "../output_files/graphics_objects/";

        const string sn = "Rew1vB0TqoMIxX444UcpScARWdhgJpsJfzmyMLR32a0+EgrCjp2NaQ==";
        const 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=";

        private static void CreateResultFolder(string output_path)
        {
            if (!Directory.Exists(output_path))
            {
                Directory.CreateDirectory(output_path);
            }
        }

        static void AddTextObjects(PDFPage page)
        {
            long position = page.GetLastGraphicsObjectPosition(GraphicsObject.Type.e_TypeText);
            using (var text_object = TextObject.Create())
            {
                text_object.SetFillColor(0xFFFF7F00);

                // Prepare text state
                using (var state = new TextState())
                {
                    using (var font = new Font("Simsun", (int)Font.Styles.e_StylesSmallCap, Font.Charset.e_CharsetGB2312, 0))
                    {
                        state.font_size = 80.0f;
                        state.font = font;
                    }
                    state.textmode = TextState.Mode.e_ModeFill;
                    text_object.SetTextState(page, state, false, 750);

                    // Set text.
                    text_object.SetText("Foxit Software");
                    long last_position = page.InsertGraphicsObject(position, text_object);

                    var rect = text_object.GetRect();
                    float offset_x = (page.GetWidth() - (rect.right - rect.left)) / 2;
                    float offset_y = page.GetHeight() * 0.8f - (rect.top - rect.bottom) / 2;
                    text_object.Transform(new Matrix2D(1, 0, 0, 1, offset_x, offset_y), false);

                    // Generate content
                    page.GenerateContent();

                    // Clone a text object from the old text object.
                    using (var font = new Font(Font.StandardID.e_StdIDTimes))
                    {
                        using (var text_object2 = text_object.Clone().GetTextObject())
                        {
                            state.font = font;
                            state.font_size = 48.0f;
                            state.textmode = TextState.Mode.e_ModeFillStrokeClip;

                            text_object2.SetTextState(page, state, true, 750);
                            text_object2.SetText("www.foxitsoftware.com");

                            text_object2.SetFillColor(0xFFAAAAAA);
                            text_object2.SetStrokeColor(0xFFF68C21);
                            page.InsertGraphicsObject(last_position, text_object2);

                            rect = text_object2.GetRect();
                            offset_x = (page.GetWidth() - (rect.right - rect.left)) / 2;
                            offset_y = page.GetHeight() * 0.618f - (rect.top - rect.bottom) / 2;
                            text_object2.Transform(new Matrix2D(1, 0, 0, 1, offset_x, offset_y), false);

                            // Generate content again after transformation.
                            page.GenerateContent();
							
                            //Show how to get the characters' information of text object.
                            int text_object_charcount = text_object2.GetCharCount();
                            FileStream sfile = new FileStream(output_path + "text_objects_info.txt", FileMode.OpenOrCreate);
                            StreamWriter sw = new StreamWriter(sfile);
                            sw.WriteLine("The new text object has " + text_object_charcount + "characters.");

                            for (int i = 0; i < text_object_charcount; i++)
                            {
                                //The character's position.
                                PointF char_pos = text_object2.GetCharPos(i);
                                //The character's width.
                                float width = text_object2.GetCharWidthByIndex(i);
                                //The character's height.
                                float height = text_object2.GetCharHeightByIndex(i);

                                sw.WriteLine("The position of the " + i + " characters is (" + char_pos.x + "," + char_pos.y + ").The width and height of the characters is (" + width + "," + height + ").");
                            }

                            sw.Close();
                            sfile.Close();
                        }
                    }
                }
            }
        }

        public static void AddPieces(PDFPage page, GraphicsObject orignal_pieces, RectF dst_rect)
        {
            long position = page.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeAll);
            using (var pieces = orignal_pieces.Clone())
            {

                var piece_rect = pieces.GetRect();

                // Calculates the transformation matrix between dst_rect and  piece_rect.
                float a = (dst_rect.right - dst_rect.left) / (piece_rect.right - piece_rect.left);
                float d = (dst_rect.top - dst_rect.bottom) / (piece_rect.top - piece_rect.bottom);
                float e = dst_rect.left - piece_rect.left * a;
                float f = dst_rect.top - piece_rect.top * d;

                // Transform rect.
                pieces.Transform(new Matrix2D(a, 0, 0, d, e, f), false);
                page.InsertGraphicsObject(position, pieces);

                page.GenerateContent();
            }
        }

        public static void AddPathObjects(PDFPage page, GraphicsObject black_pieces, GraphicsObject white_pieces)
        {
            long position = page.GetLastGraphicsObjectPosition(GraphicsObject.Type.e_TypePath);
            using (var path_object = PathObject.Create())
            {
                using (var path = new foxit.common.Path())
                {
                    float page_width = page.GetWidth();
                    float page_height = page.GetHeight();

                    float width = Math.Min(page_width, page_height) / 20.0f;
                    float start_x = (page_width - width * 18.0f) / 2.0f;
                    float start_y = (page_height - width * 18.0f) / 2.0f;

                    // Draw a chess board
                    for (int i = 0; i < 19; i++)
                    {
                        float x1 = start_x;
                        float y1 = i * width + start_y;

                        float x2 = start_x + 18 * width;
                        path.MoveTo(new PointF(x1, y1));
                        path.LineTo(new PointF(x2, y1));

                        x1 = i * width + start_x;
                        y1 = start_y;

                        float y2 = 18 * width + start_y;
                        path.MoveTo(new PointF(x1, y1));
                        path.LineTo(new PointF(x1, y2));
                    }

                    int[] star = { 3, 9, 15 };
                    for (int i = 0; i < 3; i++)
                    {
                        for (int j = 0; j < 3; j++)
                        {
                            var rect = new RectF(start_x + star[i] * width - width / 12, start_y + star[j] * width - width / 12,
                                start_x + star[i] * width + width / 12, start_y + star[j] * width + width / 12);
                            path.AppendEllipse(rect);
                        }
                    }
                    path_object.SetPathData(path);

                    path_object.SetFillColor(0xFF000000);
                    path_object.SetFillMode(FillMode.e_FillModeAlternate);
                    path_object.SetStrokeState(true);
                    path_object.SetStrokeColor(0xFF000000);

                    page.InsertGraphicsObject(position, path_object);
                    page.GenerateContent();

                    // Draw pieces
                    var pieces_vector = new PointF[][]{new PointF[]{new PointF(3, 3), new PointF(3, 7), new PointF(3, 15), new PointF(13, 2),
                        new PointF(13, 16), new PointF(13, 17), new PointF(15, 16), new PointF(16, 16)},
                        new PointF[]{new PointF(11, 16), new PointF(12, 14), new PointF(14, 4), new PointF(14, 15),
                        new PointF(15, 3), new PointF(15, 9), new PointF(15, 15), new PointF(16, 15)}};
                    for (int k = 0; k < 2; k++)
                    {
                        for (int i = 0; i < pieces_vector[k].Length; i++)
                        {
                            int x = (int)pieces_vector[k][i].x;
                            int y = (int)pieces_vector[k][i].y;
                            AddPieces(page, (k % 2 != 0) ? white_pieces : black_pieces,
                                                    new RectF(start_x + x * width - width / 2.0f, start_y + y * width - width / 2.0f,
                                                            start_x + x * width + width / 2.0f, start_y + y * width + width / 2.0f));
                        }
                    }
                }
            }
        }

        public static void AddImageObjects(PDFPage page, string image_file)
        {
            long position = page.GetLastGraphicsObjectPosition(GraphicsObject.Type.e_TypeImage);
            using (var image = new Image(image_file))
            {
                using (var doc = page.GetDocument())
                {
                    using (var image_object = ImageObject.Create(doc))
                    {
                        image_object.SetImage(image, 0);

                        float width = image.GetWidth();
                        float height = image.GetHeight();
                        float page_width = page.GetWidth();
                        float page_height = page.GetHeight();

                        // Please notice the matrix value.
                        image_object.SetMatrix(new Matrix2D(width, 0, 0, height, (page_width - width) / 2.0f, (page_height - height) / 2.0f));
                        page.InsertGraphicsObject(position, image_object);
                        page.GenerateContent();
                    }
                }
            }
        }
        static void Main(string[] args)
        {
            CreateResultFolder(output_path);
            // Initialize library
            ErrorCode error_code = Library.Initialize(sn, key);
            if (error_code != ErrorCode.e_ErrSuccess)
            {
                Console.WriteLine("Library Initialize Error: {0}", error_code);
                return;
            }

            try
            {
                string input_file = input_path + "graphics_objects.pdf";
                using (var doc = new PDFDoc(input_file))
                {
                    error_code = doc.Load(null);

                    if (error_code != ErrorCode.e_ErrSuccess)
                    {
                        Console.WriteLine("The PDFDoc {0} Error: {1}", input_file, error_code);
                        return;
                    }
                    // Get original shading objects from PDF page.
                    using (var original_page = doc.GetPage(0))
                    {
                        using (var progressive = original_page.StartParse((int)PDFPage.ParseFlags.e_ParsePageNormal, null, false))
                        {
                            long position = original_page.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeShading);
                            if (position == 0)
                            {
                                return;
                            }
                            using (var black_pieces = original_page.GetGraphicsObject(position))
                            {
                                position = original_page.GetNextGraphicsObjectPosition(position, GraphicsObject.Type.e_TypeShading);
                                using (var white_pieces = original_page.GetGraphicsObject(position))
                                {

                                    // Add a new PDF page and insert text objects.
                                    using (var page = doc.InsertPage(0, PDFPage.Size.e_SizeLetter))
                                    {
                                        AddTextObjects(page);
                                    }

                                    // Add a new PDF page and insert image objects.
                                    using (var page = doc.InsertPage(1, PDFPage.Size.e_SizeLetter))
                                    {
                                        string image_file = input_path + "sdk.png";
                                        AddImageObjects(page, image_file);
                                    }

                                    // Add a new PDF page and insert path objects, and copy shading objects.
                                    using (var page = doc.InsertPage(2, PDFPage.Size.e_SizeLetter))
                                    {
                                        AddPathObjects(page, black_pieces, white_pieces);
                                    }
                                    string output_file = output_path + "graphics_objects.pdf";
                                    doc.SaveAs(output_file, (int)PDFDoc.SaveFlags.e_SaveFlagNormal);
                                }
                            }
                        }
                    }
                }
                Console.WriteLine("Add graphics objects to PDF file.");

                //Remove text objects from PDF page.
                using (var doc = new PDFDoc(output_path + "graphics_objects.pdf"))
                {
                    error_code = doc.Load(null);

                    if (error_code != ErrorCode.e_ErrSuccess)
                    {
                        Console.WriteLine("The PDFDoc {0} Error: {1}", input_file, error_code);
                        return;
                    }
                    using (var page = doc.GetPage(0))
                    {
                        page.StartParse((int)PDFPage.ParseFlags.e_ParsePageNormal, null, false);
                        long position = page.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeAll);
                        while(position!=0)
                        {
                            using (var obj = page.GetGraphicsObject(position))
                            {
                                if(obj.GetType()==GraphicsObject.Type.e_TypeText)
                                {
                                    TextObject textobj = obj.GetTextObject();
                                    string s = textobj.GetText();
                                    if (s.Length > 0)
                                    {
                                        page.RemoveGraphicsObject(textobj);
                                        position = page.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeAll);
                                        continue;
                                    }
                                }
                                else if(obj.GetType()==GraphicsObject.Type.e_TypeFormXObject)
                                {
                                    FormXObject formxobj = obj.GetFormXObject();
                                    GraphicsObjects graphicsObjects_form = formxobj.GetGraphicsObjects();
                                    long pos = graphicsObjects_form.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeText);
                                    if(pos != 0)
                                    {
                                        TextObject textobj = page.GetGraphicsObject(pos).GetTextObject();
                                        if (textobj.GetType() == GraphicsObject.Type.e_TypeText)
                                        {
                                            string s = textobj.GetText();
                                            if(s.Length>0)
                                            {
                                                page.RemoveGraphicsObject(obj);
                                                position = page.GetFirstGraphicsObjectPosition(GraphicsObject.Type.e_TypeAll);
                                                continue;
                                            }
                                        }
                                    }
                                }
                                position = page.GetNextGraphicsObjectPosition(position, GraphicsObject.Type.e_TypeAll);
                            }
                        }
                        page.GenerateContent();
                    }
                    string output_file = output_path + "graphics_objects_remove_text_objects.pdf";
                    doc.SaveAs(output_file, (int)PDFDoc.SaveFlags.e_SaveFlagNormal);
                }
                Console.WriteLine("Remove text objects from PDF file.");
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Library.Release();
        }
    }
}
