Bläddra i källkod

ComPDFKit.Tool(win) - 填写签名交互部分

liyuxuan 1 månad sedan
förälder
incheckning
3d4d48880a

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs

@@ -2112,7 +2112,7 @@ namespace ComPDFKit.Tool
             {
                 case MouseHitTestType.Unknown:
                     {
-                        if (currentToolType == ToolType.CreateAnnot)
+                        if (currentToolType == ToolType.CreateAnnot && e.mouseButtonEventArgs!=null)
                         {
                             switch ((e.mouseButtonEventArgs as MouseButtonEventArgs).ClickCount)
                             {
@@ -2284,7 +2284,7 @@ namespace ComPDFKit.Tool
             {
                 case ToolType.Pan:
                     {
-                        if (e.annotType == C_ANNOTATION_TYPE.C_ANNOTATION_NONE)
+                        if (e.annotType == C_ANNOTATION_TYPE.C_ANNOTATION_NONE && e.mouseButtonEventArgs!=null)
                         {
                             switch ((e.mouseButtonEventArgs as MouseButtonEventArgs).ClickCount)
                             {

+ 1 - 1
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs

@@ -51,7 +51,7 @@ namespace ComPDFKit.Tool
         Border textBorder;
         TextBox textui;
         BaseAnnot caheMoveAnnot;
-        BaseAnnot cacheHitTestAnnot;
+        internal BaseAnnot cacheHitTestAnnot;
         bool isCacheRedaction = false;
         int createAnnotTag = -1;
         int selectedPageIndex = -1;

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotEdit.cs

@@ -91,7 +91,7 @@ namespace ComPDFKit.Tool
             }
         }
 
-        private void DrawEditAnnotLayer()
+        internal void DrawEditAnnotLayer()
         {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(annotEditViewTag);
             AnnotEdit annotEdit = CommonHelper.FindVisualChild<AnnotEdit>(baseLayer as CustomizeLayer);
@@ -120,7 +120,7 @@ namespace ComPDFKit.Tool
             return false;
         }
 
-        private void SetEditAnnotObject()
+        internal void SetEditAnnotObject()
         {
             if (cacheHitTestAnnot == null)
             {

+ 5 - 5
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs

@@ -17,7 +17,7 @@ namespace ComPDFKit.Tool
 {
     public partial class CPDFViewerTool
     {
-        bool isDrawSelectRect = false;
+        internal bool isDrawSelectRect = false;
         int selectedRectViewTag = -1;
         private bool isOutSideScaling = false;
         public event EventHandler<SelectedAnnotData> SelectedDataChanging;
@@ -136,7 +136,7 @@ namespace ComPDFKit.Tool
             }
         }
 
-        private void SelectedAnnot()
+        internal void SelectedAnnot()
         {
             if (!isHitTestLink&& cacheHitTestAnnot?.CurrentType== C_ANNOTATION_TYPE.C_ANNOTATION_LINK)
             {
@@ -149,7 +149,7 @@ namespace ComPDFKit.Tool
             SelectAnnot(cacheHitTestAnnot.GetAnnotData());
         }
 
-        private void SelectAnnot(AnnotData selectData)
+        internal void SelectAnnot(AnnotData selectData)
         {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectedRectViewTag);
             SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
@@ -179,7 +179,7 @@ namespace ComPDFKit.Tool
         /// <summary>
         /// Refresh the drawing
         /// </summary>
-        private void DrawSelectedLayer()
+        internal void DrawSelectedLayer()
         {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectedRectViewTag);
             SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
@@ -193,7 +193,7 @@ namespace ComPDFKit.Tool
         /// Identify whether the mouse is on the rectangle
         /// </summary>
         /// <returns></returns>
-        private bool DrawSelectRectDownEvent()
+        internal bool DrawSelectRectDownEvent()
         {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectedRectViewTag);
 

+ 24 - 2
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs

@@ -4,6 +4,7 @@ using ComPDFKit.PDFDocument;
 using ComPDFKit.PDFDocument.Action;
 using ComPDFKit.PDFPage;
 using ComPDFKit.Tool.DrawTool;
+using ComPDFKit.Tool.FillTool;
 using ComPDFKit.Tool.Help;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Viewer.Helper;
@@ -97,8 +98,13 @@ namespace ComPDFKit.Tool
             InsertPageSelectedRectView();
 
             AnnotSelectInsert();
+            FillManager = new FillManager(this);
         }
 
+        internal void InvokeMouseLeftDown(MouseEventObject e)
+        {
+            MouseLeftButtonDownHandler?.Invoke(this, e);
+        }
         private void Current_Exit(object sender, ExitEventArgs e)
         {
             GetCPDFViewer().Dispose();
@@ -130,8 +136,7 @@ namespace ComPDFKit.Tool
 
         private bool isMultiSelected;
         private bool isDocumentModified = false;
-
-
+        public FillManager FillManager { get; private set; }
 
         public bool CanAddTextEdit = true;
 
@@ -349,6 +354,12 @@ namespace ComPDFKit.Tool
                 RemovePopTextUI();
             }
             Focus();
+
+            if (FillManager?.MouseDownHandle(e) == true)
+            {
+                return;
+            }
+
             Mouse.Capture(this, CaptureMode.SubTree);
             MouseEventObject mouseEventObject = new MouseEventObject
             {
@@ -600,6 +611,12 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
+
+            if (FillManager?.MouseUpHandle(e) == true)
+            {
+                return;
+            }
+
             if (currentModel == ToolType.WidgetEdit)
             {
                 bool areaSelectAdd = AnnotSelectAreaSelect(true);
@@ -681,6 +698,11 @@ namespace ComPDFKit.Tool
                 return;
             }
 
+            if(FillManager?.MouseMoveHandle(e)==true)
+            {
+                return;
+            }
+
             Cursor oldCursor = this.Cursor;
             Cursor newCursor = this.Cursor;
             MouseEventObject mouseEventObject = new MouseEventObject

+ 2 - 0
Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj

@@ -130,6 +130,8 @@
     <Compile Include="DrawTool\SelectedRect.protected.cs" />
     <Compile Include="DrawTool\SelectImage.cs" />
     <Compile Include="DrawTool\SelectText.cs" />
+    <Compile Include="FillTool\FillCreate.cs" />
+    <Compile Include="FillTool\FillManager.cs" />
     <Compile Include="Help\CommonHelper.cs" />
     <Compile Include="Help\ImportWin32.cs" />
     <Compile Include="Help\ParamConverter.cs" />

+ 928 - 0
Demo/Examples/ComPDFKit.Tool/FillTool/FillCreate.cs

@@ -0,0 +1,928 @@
+using ComPDFKit.Import;
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFDocument;
+using ComPDFKit.PDFPage;
+using ComPDFKit.Tool.Help;
+using ComPDFKit.Tool.UndoManger;
+using ComPDFKitViewer;
+using ComPDFKitViewer.Annot;
+using ComPDFKitViewer.Helper;
+using ComPDFKitViewer.Layer;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+
+namespace ComPDFKit.Tool.FillTool
+{
+    internal class FillCreateTool : BaseLayer
+    {
+        internal CPDFViewer PDFViewer { get; set; }
+        internal int PageIndex { get; set; } = -1;
+        internal Point MouseDownPos { get; set; } = new Point(-1, -1);
+        internal Point CurrentMousePos { get; set; } = new Point(-1, -1);
+        internal Rect PageBound { get; set; } = Rect.Empty;
+        internal FillItem FillParam { get; private set; }
+        internal bool IsMouseMoved { get; set; }
+        private Rect DrawBound { get; set; }
+        private double DPIScale { get; set; } = 96D / 72D;
+        public override void Draw()
+        {
+            if (FillParam == null || PDFViewer == null)
+            {
+                return;
+            }
+
+            Point mousePos = Mouse.GetPosition(PDFViewer);
+            Rect viewRect = new Rect(0, 0, PDFViewer.ActualWidth, PDFViewer.ActualHeight);
+            if (viewRect.Contains(mousePos) == false && Mouse.LeftButton == MouseButtonState.Released)
+            {
+                return;
+            }
+
+            if (CurrentMousePos.X == -1 || CurrentMousePos.Y == -1)
+            {
+                return;
+            }
+
+            DrawingContext drawDC = Open();
+            switch (FillParam.Type)
+            {
+                case FillType.Square:
+                    DrawRect(drawDC);
+                    break;
+                case FillType.Circle:
+                    DrawCircle(drawDC);
+                    break;
+                case FillType.Line:
+                    DrawLine(drawDC);
+                    break;
+                case FillType.Cross:
+                    DrawCross(drawDC);
+                    break;
+                case FillType.Check:
+                    DrawCheck(drawDC);
+                    break;
+                default:
+                    break;
+            }
+          
+            Present();
+        }
+
+        internal void SetFillParam(FillItem param)
+        {
+            FillParam = param;
+        }
+
+        private void DrawCircle(DrawingContext drawDC)
+        {
+            if (FillParam == null || FillParam.Param == null)
+            {
+                return;
+            }
+
+            CircleParam circleParam = FillParam.Param as CircleParam;
+            if (circleParam == null)
+            {
+                return;
+            }
+
+            try
+            {
+                double zoom = PDFViewer.GetZoom();
+                SolidColorBrush fillBrush = Brushes.Black;
+                if (circleParam.BgColor != null && circleParam.BgColor.Length == 3)
+                {
+                    fillBrush = new SolidColorBrush(Color.FromRgb(circleParam.BgColor[0], circleParam.BgColor[1], circleParam.BgColor[2]));
+                }
+
+                if (PageIndex >= 0 && Mouse.LeftButton == MouseButtonState.Pressed)
+                {
+                    double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+                    xPos = Math.Min(xPos, PageBound.Right);
+                    double yPos = Math.Max(PageBound.Top, CurrentMousePos.Y);
+                    yPos = Math.Min(yPos, PageBound.Bottom);
+
+                    double centerX = (MouseDownPos.X + xPos) / 2;
+                    double centerY = (MouseDownPos.Y + yPos) / 2;
+                    double radioX = Math.Abs((MouseDownPos.X - xPos) / 2);
+                    double radioY = Math.Abs((MouseDownPos.Y - yPos) / 2);
+
+                    if (FillParam.KeepRate)
+                    {
+                        double minRadio = Math.Min(radioX, radioY);
+                        radioX = minRadio;
+                        radioY = minRadio;
+                        centerX = MouseDownPos.X + ((xPos - MouseDownPos.X) >= 0 ? 1 : -1) * radioX;
+                        centerY = MouseDownPos.Y + ((yPos - MouseDownPos.Y) >= 0 ? 1 : -1) * radioX;
+                    }
+                    DrawBound = new Rect(centerX - radioX, centerY - radioY, radioX * 2, radioY * 2);
+                    drawDC.DrawEllipse(fillBrush, null, new Point(centerX, centerY), radioX, radioY);
+                    return;
+                }
+                DrawBound = new Rect(CurrentMousePos.X - FillParam.Width * zoom / 2, CurrentMousePos.Y - FillParam.Height * zoom / 2, FillParam.Width * zoom, FillParam.Height * zoom);
+                drawDC.DrawEllipse(fillBrush, null, CurrentMousePos, FillParam.Width * zoom/2, FillParam.Height * zoom/2);
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void DrawRect(DrawingContext drawDC)
+        {
+            if (FillParam == null || FillParam.Param == null)
+            {
+                return;
+            }
+
+            SquareParam squareParam = FillParam.Param as SquareParam;
+            if (squareParam == null)
+            {
+                return;
+            }
+
+            try
+            {
+                double zoom = PDFViewer.GetZoom();
+                SolidColorBrush lineBrush = Brushes.Black;
+                if (squareParam.LineColor != null && squareParam.LineColor.Length == 3)
+                {
+                    lineBrush = new SolidColorBrush(Color.FromRgb(squareParam.LineColor[0], squareParam.LineColor[1], squareParam.LineColor[2]));
+                }
+
+                Pen borderPen = new Pen(lineBrush, squareParam.LineWidth * zoom * DPIScale);
+                int halfPenWidth = (int)Math.Ceiling(borderPen.Thickness / 2);
+
+                if (PageIndex >= 0 && Mouse.LeftButton == MouseButtonState.Pressed)
+                {
+                    double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+                    xPos = Math.Min(xPos, PageBound.Right);
+                    double yPos = Math.Max(PageBound.Top, CurrentMousePos.Y);
+                    yPos = Math.Min(yPos, PageBound.Bottom);
+
+                    double centerX = (MouseDownPos.X + xPos) / 2;
+                    double centerY = (MouseDownPos.Y + yPos) / 2;
+                    double radioX = Math.Abs((MouseDownPos.X - xPos) / 2);
+                    double radioY = Math.Abs((MouseDownPos.Y - yPos) / 2);
+
+                    if (FillParam.KeepRate)
+                    {
+                        double minRadio = Math.Min(radioX, radioY);
+                        radioX = minRadio;
+                        radioY = minRadio;
+                        centerX = MouseDownPos.X + ((xPos - MouseDownPos.X) >= 0 ? 1 : -1) * radioX;
+                        centerY = MouseDownPos.Y + ((yPos - MouseDownPos.Y) >= 0 ? 1 : -1) * radioY;
+                    }
+                    DrawBound = new Rect(centerX - radioX, centerY - radioY, radioX * 2, radioY * 2);
+                    drawDC.DrawRectangle(null, borderPen, new Rect(DrawBound.Left + halfPenWidth, DrawBound.Top + halfPenWidth, DrawBound.Width - 2 * halfPenWidth, DrawBound.Height - 2 * halfPenWidth));
+                    return;
+                }
+                DrawBound = new Rect(
+                    CurrentMousePos.X - FillParam.Width / 2 * zoom,
+                    CurrentMousePos.Y - FillParam.Height / 2 * zoom,
+                    FillParam.Width * zoom, FillParam.Height * zoom);
+
+                drawDC.DrawRectangle(null, borderPen, new Rect(DrawBound.Left + halfPenWidth, DrawBound.Top + halfPenWidth, DrawBound.Width - 2 * halfPenWidth, DrawBound.Height - 2 * halfPenWidth));
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void DrawLine(DrawingContext drawDC)
+        {
+            if (FillParam == null || FillParam.Param == null)
+            {
+                return;
+            }
+
+            LineParam lineParam = FillParam.Param as LineParam;
+            if (lineParam == null)
+            {
+                return;
+            }
+
+            try
+            {
+                double zoom = PDFViewer.GetZoom();
+                SolidColorBrush lineBrush = Brushes.Black;
+                if (lineParam.LineColor != null && lineParam.LineColor.Length == 3)
+                {
+                    lineBrush = new SolidColorBrush(Color.FromRgb(lineParam.LineColor[0], lineParam.LineColor[1], lineParam.LineColor[2]));
+                }
+
+                Pen borderPen = new Pen(lineBrush, lineParam.LineWidth * zoom);
+                if (PageIndex >= 0 && Mouse.LeftButton == MouseButtonState.Pressed)
+                {
+                    double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+                    xPos = Math.Min(xPos, PageBound.Right);
+                    DrawBound = new Rect(new Point(xPos, MouseDownPos.Y), MouseDownPos);
+                    drawDC.DrawLine(borderPen, new Point(xPos, MouseDownPos.Y), MouseDownPos);
+                    return;
+                }
+
+                Point leftPos = new Point(
+                        CurrentMousePos.X - FillParam.Width / 2 * zoom,
+                        CurrentMousePos.Y);
+                Point rightPos = new Point(
+                        CurrentMousePos.X + FillParam.Width / 2 * zoom,
+                        CurrentMousePos.Y);
+                DrawBound = new Rect(leftPos, rightPos);
+                drawDC.DrawLine(borderPen, leftPos, rightPos);
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void GetPointsBound(List<CPoint> checkList, out Rect checkBound)
+        {
+            checkBound = new Rect(0, 0, 0, 0);
+            if (checkList == null || checkList.Count == 0)
+            {
+                return;
+            }
+
+            int left = 0;
+            int top = 0;
+            int right = 0;
+            int bottom = 0;
+
+            foreach (CPoint point in checkList)
+            {
+                left = (int)Math.Min(left, point.x);
+                top = (int)Math.Min(t, point.y);
+                right = (int)Math.Max(right, point.x);
+                bottom = (int)Math.Max(bottom, point.y);
+            }
+
+            checkBound = new Rect(left, top, right - left, bottom - top);
+        }
+
+        private void DrawCheck(DrawingContext drawDC)
+        {
+            if (FillParam == null || FillParam.Param == null)
+            {
+                return;
+            }
+
+            InkParam inkParam = FillParam.Param as InkParam;
+            if (inkParam == null)
+            {
+                return;
+            }
+
+            try
+            {
+                double zoom = PDFViewer.GetZoom();
+                SolidColorBrush inkBrush = Brushes.Black;
+                if (inkParam.InkColor != null && inkParam.InkColor.Length == 3)
+                {
+                    inkBrush = new SolidColorBrush(Color.FromRgb(inkParam.InkColor[0], inkParam.InkColor[1], inkParam.InkColor[2]));
+                }
+
+                Pen borderPen = new Pen(inkBrush, inkParam.Thickness * zoom);
+                borderPen.StartLineCap=PenLineCap.Round;
+                borderPen.EndLineCap=PenLineCap.Round;
+
+                if (inkParam.InkPath == null || inkParam.InkPath.Count == 0)
+                {
+                    int width = Math.Max(0, FillParam.Width);
+                    int height = Math.Max(0, FillParam.Height);
+                    if (width == 0 || height == 0)
+                    {
+                        width = 30;
+                        height = 30;
+                    }
+
+                    List<List<CPoint>> defaultList = new List<List<CPoint>>();
+                    List<CPoint> pointList = new List<CPoint>();
+                    defaultList.Add(pointList);
+
+                    pointList.Add(new CPoint(0, height * 2 / 3));
+                    pointList.Add(new CPoint(width / 3, height));
+                    pointList.Add(new CPoint(width, height / 3));
+
+                    inkParam.InkPath = defaultList;
+                }
+
+                if (inkParam.InkPath != null && inkParam.InkPath.Count > 0)
+                {
+                    double minX = 0;
+                    double minY = 0;
+                    double maxX = 0;
+                    double maxY = 0;
+
+                    foreach (List<CPoint> loopItems in inkParam.InkPath)
+                    {
+                        GetPointsBound(loopItems, out Rect checkBound);
+                        minX = Math.Min(minX, checkBound.X);
+                        minY = Math.Min(minY, checkBound.Y);
+                        maxX = Math.Max(maxX, checkBound.Right);
+                        maxY = Math.Max(maxY, checkBound.Bottom);
+                    }
+
+                    Rect prevRect = new Rect(minX, minY, maxX - minX, maxY - minY);
+                    if (prevRect.Width == 0 || prevRect.Height == 0)
+                    {
+                        return;
+                    }
+
+                    List<List<Point>> drawPathList = new List<List<Point>>();
+                    foreach (List<CPoint> loopItems in inkParam.InkPath)
+                    {
+                        List<Point> drawPath = new List<Point>();
+                        foreach (CPoint item in loopItems)
+                        {
+                            drawPath.Add(new Point(item.x - minX, item.y - minY));
+                        }
+
+                        if (drawPath.Count >= 2)
+                        {
+                            drawPathList.Add(drawPath);
+                        }
+                    }
+                    double offsetX = (maxX - minX) / 2;
+                    double offsetY = (maxY - minY) / 2;
+                    Point centerPoint = CurrentMousePos;
+                    if (PageIndex >= 0 && Mouse.LeftButton == MouseButtonState.Pressed)
+                    {
+                        double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+                        xPos = Math.Min(xPos, PageBound.Right);
+                        double yPos = Math.Max(PageBound.Top, CurrentMousePos.Y);
+                        yPos = Math.Min(yPos, PageBound.Bottom);
+
+                        if (FillParam.KeepRate)
+                        {
+                            if (GetRateMoveSize(prevRect, out Point ratePoint) == false)
+                            {
+                                return;
+                            }
+                            xPos = ratePoint.X;
+                            yPos = ratePoint.Y;
+                        }
+                        Rect drawRect = new Rect(MouseDownPos, new Point(xPos, yPos));
+                        if (drawRect.Width == 0 || drawRect.Height == 0)
+                        {
+                            return;
+                        }
+
+                        double rateX = drawRect.Width / prevRect.Width / zoom;
+                        double rateY = drawRect.Height / prevRect.Height / zoom;
+
+                        if (FillParam.KeepRate)
+                        {
+                            rateY = rateX * prevRect.Height / prevRect.Width;
+                        }
+
+                        offsetX = (offsetX * rateX);
+                        offsetY = (offsetY * rateY);
+
+                        List<List<Point>> rateList = new List<List<Point>>();
+                        foreach (List<Point> loopItems in drawPathList)
+                        {
+                            List<Point> ratePath = new List<Point>();
+                            foreach (Point item in loopItems)
+                            {
+                                ratePath.Add(new Point((item.X - minX) * rateX, (item.Y - minY) * rateY));
+                            }
+
+                            rateList.Add(ratePath);
+                        }
+
+                        drawPathList = rateList;
+                        centerPoint.X = (MouseDownPos.X + xPos) / 2;
+                        centerPoint.Y = (MouseDownPos.Y + yPos) / 2;
+                    }
+
+                    GeometryGroup drawGroup = new GeometryGroup();
+                    foreach (List<Point> loopItems in drawPathList)
+                    {
+                        PathGeometry pathGeometry = new PathGeometry();
+                        PathFigure path = new PathFigure();
+                        path.IsClosed = false;
+                        path.StartPoint = new Point((loopItems[0].X - offsetX) * zoom + centerPoint.X, (loopItems[0].Y - offsetY) * zoom + centerPoint.Y);
+                        for (int i = 1; i < loopItems.Count; i++)
+                        {
+                            LineSegment segment = new LineSegment();
+                            segment.IsSmoothJoin = true;
+                            segment.Point = new Point((loopItems[i].X - offsetX) * zoom + centerPoint.X, (loopItems[i].Y - offsetY) * zoom + centerPoint.Y);
+                            path.Segments.Add(segment);
+                        }
+                        pathGeometry.Figures.Add(path);
+
+                        drawGroup.Children.Add(pathGeometry);
+                    }
+                    DrawBound = drawGroup.Bounds;
+                    drawDC.DrawGeometry(null, borderPen, drawGroup);
+                    return;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void DrawCross(DrawingContext drawDC)
+        {
+            if (FillParam == null || FillParam.Param == null)
+            {
+                return;
+            }
+
+            InkParam inkParam = FillParam.Param as InkParam;
+            if (inkParam == null)
+            {
+                return;
+            }
+
+            try
+            {
+                double zoom = PDFViewer.GetZoom();
+                SolidColorBrush inkBrush = Brushes.Black;
+                if (inkParam.InkColor != null && inkParam.InkColor.Length == 3)
+                {
+                    inkBrush = new SolidColorBrush(Color.FromRgb(inkParam.InkColor[0], inkParam.InkColor[1], inkParam.InkColor[2]));
+                }
+
+                Pen borderPen = new Pen(inkBrush, inkParam.Thickness * zoom);
+                borderPen.StartLineCap = PenLineCap.Round;
+                borderPen.EndLineCap = PenLineCap.Round;
+
+                if (inkParam.InkPath == null || inkParam.InkPath.Count == 0)
+                {
+                    int width = Math.Max(0, FillParam.Width);
+                    int height = Math.Max(0, FillParam.Height);
+                    if (width == 0 || height == 0)
+                    {
+                        width = 30;
+                        height = 30;
+                    }
+
+                    List<List<CPoint>> defaultList = new List<List<CPoint>>();
+                    List<CPoint> pointList = new List<CPoint>();
+                    defaultList.Add(pointList);
+
+                    pointList.Add(new CPoint(0, 0));
+                    pointList.Add(new CPoint(width / 2, height / 2));
+                    pointList.Add(new CPoint(width, height));
+
+                    pointList = new List<CPoint>();
+                    defaultList.Add(pointList);
+
+                    pointList.Add(new CPoint(0, height));
+                    pointList.Add(new CPoint(width / 2, height / 2));
+                    pointList.Add(new CPoint(width, 0));
+
+                    inkParam.InkPath = defaultList;
+                }
+
+                if (inkParam.InkPath != null && inkParam.InkPath.Count > 0)
+                {
+                    double minX = 0;
+                    double minY = 0;
+                    double maxX = 0;
+                    double maxY = 0;
+
+                    foreach (List<CPoint> loopItems in inkParam.InkPath)
+                    {
+                        GetPointsBound(loopItems, out Rect checkBound);
+                        minX = Math.Min(minX, checkBound.X);
+                        minY = Math.Min(minY, checkBound.Y);
+                        maxX = Math.Max(maxX, checkBound.Right);
+                        maxY = Math.Max(maxY, checkBound.Bottom);
+                    }
+
+                    Rect prevRect = new Rect(minX, minY, maxX - minX, maxY - minY);
+                    if (prevRect.Width == 0 || prevRect.Height == 0)
+                    {
+                        return;
+                    }
+
+                    List<List<Point>> drawPathList = new List<List<Point>>();
+                    foreach (List<CPoint> loopItems in inkParam.InkPath)
+                    {
+                        List<Point> drawPath = new List<Point>();
+                        foreach (CPoint item in loopItems)
+                        {
+                            drawPath.Add(new Point(item.x - minX, item.y - minY));
+                        }
+
+                        if (drawPath.Count >= 2)
+                        {
+                            drawPathList.Add(drawPath);
+                        }
+                    }
+                    double offsetX = (maxX - minX) / 2;
+                    double offsetY = (maxY - minY) / 2;
+                    Point centerPoint = CurrentMousePos;
+                    if (PageIndex >= 0 && Mouse.LeftButton == MouseButtonState.Pressed)
+                    {
+                        double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+                        xPos = Math.Min(xPos, PageBound.Right);
+                        double yPos = Math.Max(PageBound.Top, CurrentMousePos.Y);
+                        yPos = Math.Min(yPos, PageBound.Bottom);
+
+                        if (FillParam.KeepRate)
+                        {
+                           if(GetRateMoveSize(prevRect,out Point ratePoint)==false)
+                            {
+                                return;
+                            }
+                            xPos = ratePoint.X;
+                            yPos = ratePoint.Y;
+                        }
+                        Rect drawRect = new Rect(MouseDownPos, new Point(xPos, yPos));
+                        if (drawRect.Width == 0 || drawRect.Height == 0)
+                        {
+                            return;
+                        }
+
+                        double rateX = drawRect.Width / prevRect.Width / zoom;
+                        double rateY = drawRect.Height / prevRect.Height / zoom;
+
+                        if (FillParam.KeepRate)
+                        {
+                            rateY = rateX * prevRect.Height / prevRect.Width;
+                        }
+
+                        offsetX = (offsetX * rateX);
+                        offsetY = (offsetY * rateY);
+
+                        List<List<Point>> rateList = new List<List<Point>>();
+                        foreach (List<Point> loopItems in drawPathList)
+                        {
+                            List<Point> ratePath = new List<Point>();
+                            foreach (Point item in loopItems)
+                            {
+                                ratePath.Add(new Point((item.X - minX) * rateX, (item.Y - minY) * rateY));
+                            }
+
+                            rateList.Add(ratePath);
+                        }
+
+                        drawPathList = rateList;
+                        centerPoint.X = (MouseDownPos.X + xPos) / 2;
+                        centerPoint.Y = (MouseDownPos.Y + yPos) / 2;
+                    }
+
+                    GeometryGroup drawGroup = new GeometryGroup();
+                    foreach (List<Point> loopItems in drawPathList)
+                    {
+                        PathGeometry pathGeometry = new PathGeometry();
+                        PathFigure path = new PathFigure();
+                        path.IsClosed = false;
+                        path.StartPoint = new Point((loopItems[0].X - offsetX) * zoom + centerPoint.X, (loopItems[0].Y - offsetY) * zoom + centerPoint.Y);
+                        for (int i = 1; i < loopItems.Count; i++)
+                        {
+                            LineSegment segment = new LineSegment();
+                            segment.IsSmoothJoin=true;
+                            segment.Point = new Point((loopItems[i].X - offsetX) * zoom + centerPoint.X, (loopItems[i].Y - offsetY) * zoom + centerPoint.Y);
+                            path.Segments.Add(segment);
+                        }
+                        pathGeometry.Figures.Add(path);
+
+                        drawGroup.Children.Add(pathGeometry);
+                    }
+                    DrawBound = drawGroup.Bounds;
+                    drawDC.DrawGeometry(null, borderPen, drawGroup);
+                    return;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private bool GetRateMoveSize(Rect oldRect ,out Point ratePoint)
+        {
+            ratePoint=new Point(0,0);
+            double rateY = oldRect.Height / oldRect.Width;
+            double xPos = Math.Max(PageBound.Left, CurrentMousePos.X);
+            xPos = Math.Min(xPos, PageBound.Right);
+
+            double moveX = xPos - MouseDownPos.X;
+            double moveY = CurrentMousePos.Y - MouseDownPos.Y;
+            if (moveX == 0)
+            {
+                return false;
+            }
+            if (moveY == 0)
+            {
+                moveY = 1;
+            }
+            double rateMoveY = Math.Abs(moveX * rateY);
+            double yPos = MouseDownPos.Y + rateMoveY * Math.Abs(moveY) / moveY;
+            if (yPos >= PageBound.Top && yPos <= PageBound.Bottom)
+            {
+                ratePoint= new Point(xPos, yPos);
+                return true;
+            }
+
+            if(moveY>=0)
+            {
+                rateMoveY=PageBound.Bottom-MouseDownPos.Y;
+                yPos=PageBound.Bottom;
+            }
+            else
+            {
+                rateMoveY=MouseDownPos.Y-PageBound.Top;
+                yPos=PageBound.Top;
+            }
+
+            double rateMoveX = rateMoveY / rateY;
+            xPos = MouseDownPos.X + rateMoveX * Math.Abs(moveX) / (moveX);
+            ratePoint = new Point(xPos, yPos);
+            return true;
+        }
+
+        internal FillItem SaveFillItem()
+        {
+            if (FillParam == null || PageIndex < 0 || PDFViewer == null)
+            {
+                return null;
+            }
+
+            try
+            {
+                switch (FillParam.Type)
+                {
+                    case FillType.Square:
+                        return SaveRect();
+                    case FillType.Circle:
+                        return SaveCircle();
+                    case FillType.Line:
+                        return SaveLine();
+                    case FillType.Check:
+                        return SaveCheck();
+                    case FillType.Cross:
+                        return SaveCross();
+                    default:
+                        return null;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+            return null;
+        }
+
+        private FillItem SaveRect()
+        {
+            double zoom = PDFViewer.GetZoom();
+            CPDFDocument pdfDoc = PDFViewer.GetDocument();
+            if (zoom <= 0 || pdfDoc == null)
+            {
+                return null;
+            }
+            CPDFPage pdfPage = pdfDoc.PageAtIndex(PageIndex);
+            SquareParam param = FillParam.Param as SquareParam;
+            if (pdfPage == null || param == null)
+            {
+                return null;
+            }
+
+            Rect offsetRect = new Rect(DrawBound.X - PageBound.X, DrawBound.Y - PageBound.Y, DrawBound.Width, DrawBound.Height);
+            Rect standRect = new Rect(offsetRect.X / zoom, offsetRect.Y / zoom, offsetRect.Width / zoom, offsetRect.Height / zoom);
+            Rect pdfRect = new Rect(standRect.X / 96D * 72D, standRect.Y / 96D * 72D, standRect.Width / 96D * 72D, standRect.Height / 96D * 72D);
+
+            CPDFSquareAnnotation squareAnnot = (CPDFSquareAnnotation)pdfPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE);
+            squareAnnot.SetRect(new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top));
+            squareAnnot.SetLineWidth((float)param.LineWidth);
+            squareAnnot.SetLineColor(param.LineColor);
+            squareAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+            if(string.IsNullOrEmpty(param.Author)==false)
+            {
+                squareAnnot.SetAuthor(param.Author);
+            }
+            squareAnnot.UpdateAp();
+
+            FillItem cloneItem = FillParam.Clone();
+            cloneItem.Param = ParamConverter.AnnotConverter(pdfDoc, squareAnnot);
+            cloneItem.HistoryItem = new SquareAnnotHistory();
+            cloneItem.HistoryItem.Action = HistoryAction.Add;
+            cloneItem.HistoryItem.CurrentParam = ParamConverter.AnnotConverter(pdfDoc, squareAnnot);
+            cloneItem.HistoryItem.PDFDoc = pdfDoc;
+            PDFViewer.UndoManager.AddHistory(cloneItem.HistoryItem);
+            return cloneItem;
+        }
+
+        private FillItem SaveCircle()
+        {
+            double zoom = PDFViewer.GetZoom();
+            CPDFDocument pdfDoc = PDFViewer.GetDocument();
+            if (zoom <= 0 || pdfDoc == null)
+            {
+                return null;
+            }
+            CPDFPage pdfPage = pdfDoc.PageAtIndex(PageIndex);
+            CircleParam param = FillParam.Param as CircleParam;
+            if (pdfPage == null || param == null)
+            {
+                return null;
+            }
+
+            Rect offsetRect = new Rect(DrawBound.X - PageBound.X, DrawBound.Y - PageBound.Y, DrawBound.Width, DrawBound.Height);
+            Rect standRect = new Rect(offsetRect.X / zoom, offsetRect.Y / zoom, offsetRect.Width / zoom, offsetRect.Height / zoom);
+            Rect pdfRect = new Rect(standRect.X / 96D * 72D, standRect.Y / 96D * 72D, standRect.Width / 96D * 72D, standRect.Height / 96D * 72D);
+
+            CPDFCircleAnnotation circleAnnot = (CPDFCircleAnnotation)pdfPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE);
+            circleAnnot.SetRect(new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top));
+            if (param.HasBgColor)
+            {
+                circleAnnot.SetBgColor(param.BgColor);
+                circleAnnot.SetLineColor(param.BgColor);
+            }
+
+            circleAnnot.SetLineWidth(0);
+            circleAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+            if (string.IsNullOrEmpty(param.Author) == false)
+            {
+                circleAnnot.SetAuthor(param.Author);
+            }
+            circleAnnot.UpdateAp();
+
+            FillItem cloneItem = FillParam.Clone();
+            cloneItem.Param = ParamConverter.AnnotConverter(pdfDoc, circleAnnot);
+            cloneItem.HistoryItem = new CircleAnnotHistory();
+            cloneItem.HistoryItem.Action = HistoryAction.Add;
+            cloneItem.HistoryItem.CurrentParam = ParamConverter.AnnotConverter(pdfDoc, circleAnnot);
+            cloneItem.HistoryItem.PDFDoc = pdfDoc;
+            PDFViewer.UndoManager.AddHistory(cloneItem.HistoryItem);
+            return cloneItem;
+        }
+
+        private FillItem SaveLine()
+        {
+            double zoom = PDFViewer.GetZoom();
+            CPDFDocument pdfDoc = PDFViewer.GetDocument();
+            if (zoom <= 0 || pdfDoc == null)
+            {
+                return null;
+            }
+            CPDFPage pdfPage = pdfDoc.PageAtIndex(PageIndex);
+            LineParam param = FillParam.Param as LineParam;
+            if (pdfPage == null || param == null)
+            {
+                return null;
+            }
+
+            Rect offsetRect = new Rect(DrawBound.X - PageBound.X, DrawBound.Y - PageBound.Y, DrawBound.Width, DrawBound.Height);
+            Rect standRect = new Rect(offsetRect.X / zoom, offsetRect.Y / zoom, offsetRect.Width / zoom, offsetRect.Height / zoom);
+            Rect pdfRect = new Rect(standRect.X / 96D * 72D, standRect.Y / 96D * 72D, standRect.Width / 96D * 72D, standRect.Height / 96D * 72D);
+
+            CPDFLineAnnotation lineAnnot = (CPDFLineAnnotation)pdfPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_LINE);
+            lineAnnot.SetRect(new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top));
+            lineAnnot.SetLinePoints(new CPoint((float)pdfRect.Left,(float)(pdfRect.Top+pdfRect.Height/2)),new CPoint((float)pdfRect.Right,(float)(pdfRect.Top+pdfRect.Height/2)));
+            lineAnnot.SetLineWidth((float)param.LineWidth);
+            lineAnnot.SetLineColor(param.LineColor);
+            lineAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+            if (string.IsNullOrEmpty(param.Author) == false)
+            {
+                lineAnnot.SetAuthor(param.Author);
+            }
+            lineAnnot.UpdateAp();
+
+            FillItem cloneItem = FillParam.Clone();
+            cloneItem.Param = ParamConverter.AnnotConverter(pdfDoc, lineAnnot);
+            cloneItem.HistoryItem = new LineAnnotHistory();
+            cloneItem.HistoryItem.Action = HistoryAction.Add;
+            cloneItem.HistoryItem.CurrentParam = ParamConverter.AnnotConverter(pdfDoc, lineAnnot);
+            cloneItem.HistoryItem.PDFDoc = pdfDoc;
+            PDFViewer.UndoManager.AddHistory(cloneItem.HistoryItem);
+            return cloneItem;
+        }
+
+        private FillItem SaveCheck()
+        {
+            double zoom = PDFViewer.GetZoom();
+            CPDFDocument pdfDoc = PDFViewer.GetDocument();
+            if (zoom <= 0 || pdfDoc == null)
+            {
+                return null;
+            }
+            CPDFPage pdfPage = pdfDoc.PageAtIndex(PageIndex);
+            InkParam param = FillParam.Param as InkParam;
+            if (pdfPage == null || param == null)
+            {
+                return null;
+            }
+
+            if(param==null || param.InkPath==null || param.InkPath.Count==0)
+            {
+                return null;
+            }
+            List<List<CPoint>> rawPointList = new List<List<CPoint>>();
+            Rect offsetRect = new Rect(DrawBound.X - PageBound.X, DrawBound.Y - PageBound.Y, DrawBound.Width, DrawBound.Height);
+            Rect standRect = new Rect(offsetRect.X / zoom, offsetRect.Y / zoom, offsetRect.Width / zoom, offsetRect.Height / zoom);
+            Rect pdfRect = new Rect(standRect.X / 96D * 72D, standRect.Y / 96D * 72D, standRect.Width / 96D * 72D, standRect.Height / 96D * 72D);
+
+            foreach (List<CPoint> segmentList in param.InkPath)
+            {
+                List<CPoint> pointList = new List<CPoint>();
+                foreach (CPoint point in segmentList)
+                {
+                    pointList.Add(new CPoint(point.x/96F*72F+(float)pdfRect.Left,point.y/96F*72F+(float)pdfRect.Top));
+                }
+
+                if (pointList.Count > 0)
+                {
+                    rawPointList.Add(pointList);
+                }
+            }
+
+            CPDFInkAnnotation inkAnnot = (CPDFInkAnnotation)pdfPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_INK);
+            inkAnnot.SetInkPath(rawPointList);
+            inkAnnot.SetRect(new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top));
+            inkAnnot.SetInkColor(param.InkColor);
+            inkAnnot.SetThickness((float)param.Thickness);
+            inkAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+            if (string.IsNullOrEmpty(param.Author) == false)
+            {
+                inkAnnot.SetAuthor(param.Author);
+            }
+            inkAnnot.UpdateAp();
+
+            FillItem cloneItem = FillParam.Clone();
+            cloneItem.Param = ParamConverter.AnnotConverter(pdfDoc, inkAnnot);
+            cloneItem.HistoryItem = new InkAnnotHistory();
+            cloneItem.HistoryItem.Action = HistoryAction.Add;
+            cloneItem.HistoryItem.CurrentParam = ParamConverter.AnnotConverter(pdfDoc, inkAnnot);
+            cloneItem.HistoryItem.PDFDoc = pdfDoc;
+            PDFViewer.UndoManager.AddHistory(cloneItem.HistoryItem);
+            return cloneItem;
+        }
+
+        private FillItem SaveCross()
+        {
+            double zoom = PDFViewer.GetZoom();
+            CPDFDocument pdfDoc = PDFViewer.GetDocument();
+            if (zoom <= 0 || pdfDoc == null)
+            {
+                return null;
+            }
+            CPDFPage pdfPage = pdfDoc.PageAtIndex(PageIndex);
+            InkParam param = FillParam.Param as InkParam;
+            if (pdfPage == null || param == null)
+            {
+                return null;
+            }
+
+            if (param == null || param.InkPath == null || param.InkPath.Count == 0)
+            {
+                return null;
+            }
+            List<List<CPoint>> rawPointList = new List<List<CPoint>>();
+            Rect offsetRect = new Rect(DrawBound.X - PageBound.X, DrawBound.Y - PageBound.Y, DrawBound.Width, DrawBound.Height);
+            Rect standRect = new Rect(offsetRect.X / zoom, offsetRect.Y / zoom, offsetRect.Width / zoom, offsetRect.Height / zoom);
+            Rect pdfRect = new Rect(standRect.X / 96D * 72D, standRect.Y / 96D * 72D, standRect.Width / 96D * 72D, standRect.Height / 96D * 72D);
+
+            foreach (List<CPoint> segmentList in param.InkPath)
+            {
+                List<CPoint> pointList = new List<CPoint>();
+                foreach (CPoint point in segmentList)
+                {
+                    pointList.Add(new CPoint(point.x / 96F * 72F + (float)pdfRect.Left, point.y / 96F * 72F + (float)pdfRect.Top));
+                }
+
+                if (pointList.Count > 0)
+                {
+                    rawPointList.Add(pointList);
+                }
+            }
+
+            CPDFInkAnnotation inkAnnot = (CPDFInkAnnotation)pdfPage.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_INK);
+            inkAnnot.SetInkPath(rawPointList);
+            inkAnnot.SetRect(new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top));
+            inkAnnot.SetInkColor(param.InkColor);
+            inkAnnot.SetThickness((float)param.Thickness);
+            inkAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+            if (string.IsNullOrEmpty(param.Author) == false)
+            {
+                inkAnnot.SetAuthor(param.Author);
+            }
+            inkAnnot.UpdateAp();
+
+            FillItem cloneItem = FillParam.Clone();
+            cloneItem.Param = ParamConverter.AnnotConverter(pdfDoc, inkAnnot);
+            cloneItem.HistoryItem = new InkAnnotHistory();
+            cloneItem.HistoryItem.Action = HistoryAction.Add;
+            cloneItem.HistoryItem.CurrentParam = ParamConverter.AnnotConverter(pdfDoc, inkAnnot);
+            cloneItem.HistoryItem.PDFDoc = pdfDoc;
+            PDFViewer.UndoManager.AddHistory(cloneItem.HistoryItem);
+            return cloneItem;
+        }
+    }
+}

+ 441 - 0
Demo/Examples/ComPDFKit.Tool/FillTool/FillManager.cs

@@ -0,0 +1,441 @@
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Tool.DrawTool;
+using ComPDFKit.Tool.UndoManger;
+using ComPDFKitViewer;
+using ComPDFKitViewer.BaseObject;
+using ComPDFKitViewer.Widget;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+
+namespace ComPDFKit.Tool.FillTool
+{
+
+    public enum FillType
+    {
+        Unknow,
+        Circle,
+        Square,
+        Text,
+        Line,
+        Check,
+        Cross,
+        Image
+    }
+    public class FillItem
+    {
+        public FillType Type { get; set; }
+        public int PageIndex { get; set; }
+        public int AnnotIndex { get; set; }
+        public AnnotParam Param { get; set; }
+        public int Width { get; set; }
+        public int Height { get; set; }
+        public bool KeepRate { get; set; }
+        internal AnnotHistory HistoryItem { get; set; }
+        public FillItem Clone()
+        {
+            FillItem subItem = new FillItem();
+            subItem.Type = Type;
+            subItem.PageIndex = PageIndex;
+            subItem.AnnotIndex = AnnotIndex;
+            if (Param != null)
+            {
+                switch (this.Type)
+                {
+                    case FillType.Square:
+                        SquareParam squareParam = new SquareParam();
+                        Param.CopyTo(squareParam);
+                        subItem.Param = squareParam;
+                        break;
+                    case FillType.Circle:
+                        CircleParam circleParam = new CircleParam();
+                        Param.CopyTo(circleParam);
+                        subItem.Param = circleParam;
+                        break;
+                    case FillType.Line:
+                        LineParam lineParam = new LineParam();
+                        Param.CopyTo(lineParam);
+                        subItem.Param = lineParam;
+                        break;
+                    case FillType.Check:
+                        InkParam checkParam = new InkParam();
+                        Param.CopyTo(checkParam);
+                        subItem.Param = checkParam;
+                        break;
+                    case FillType.Cross:
+                        InkParam crossParam = new InkParam();
+                        Param.CopyTo(crossParam);
+                        subItem.Param = crossParam;
+                        break;
+                    default:
+                        break;
+                }
+            }
+            subItem.Width = Width;
+            subItem.Height = Height;
+            subItem.KeepRate = KeepRate;
+
+            return subItem;
+        }
+    }
+    public class FillManager
+    {
+        private Dictionary<int, List<FillItem>> Items { get; set; } = new Dictionary<int, List<FillItem>>();
+        private CPDFViewerTool ViewTool { get; set; }
+        public CPDFToolManager ToolManager { get; set; }
+        private FillCreateTool FillCreator { get; set; }
+        private int ViewIndex { get; set; } = -1;
+        private FillItem FillParam { get; set; }
+        public bool IsFillMode { get; private set; }
+        public bool AllowFillHit { get; set; }
+        public FillManager(CPDFViewerTool tool)
+        {
+            ViewTool = tool;
+            ViewTool.MouseLeave -= ViewTool_MouseLeave;
+            ViewTool.MouseLeave += ViewTool_MouseLeave;
+            ViewTool.DrawChanged -= ViewTool_DrawChanged;
+            ViewTool.DrawChanged += ViewTool_DrawChanged;
+        }
+
+        private void ViewTool_DrawChanged(object sender, EventArgs e)
+        {
+            FillCreator?.Draw();
+        }
+
+        private void ViewTool_MouseLeave(object sender, MouseEventArgs e)
+        {
+            FillCreator?.CleanDraw();
+        }
+
+        public FillItem GetFillItem(int pageIndex, int annotIndex)
+        {
+            if (pageIndex < 0 || annotIndex < 0)
+            {
+                return null;
+            }
+
+            if (Items.ContainsKey(pageIndex))
+            {
+                foreach (FillItem item in Items[pageIndex])
+                {
+                    if (item.HistoryItem == null)
+                    {
+                        continue;
+                    }
+                    if (item.HistoryItem.GetAnnotIndex() == annotIndex)
+                    {
+                        return item;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        internal bool InsertFillLayer()
+        {
+            if (ViewTool == null && ViewTool.PDFViewer == null)
+            {
+                return false;
+            }
+
+            if (FillCreator != null)
+            {
+                return true;
+            }
+
+            CPDFViewer pdfViewer = ViewTool.PDFViewer;
+            if (ViewIndex != -1)
+            {
+                FillCreator = pdfViewer.GetViewForTag(ViewIndex) as FillCreateTool;
+                if (FillCreator != null)
+                {
+                    return true;
+                }
+            }
+
+            FillCreator = new FillCreateTool();
+            int annotViewindex = pdfViewer.GetMaxViewIndex();
+            pdfViewer.InsertView(annotViewindex, FillCreator);
+            ViewIndex = FillCreator.GetResTag();
+            FillCreator.PDFViewer = pdfViewer;
+            return true;
+        }
+
+        public bool EnableFillMode(bool isFill)
+        {
+            IsFillMode = false;
+            if (ViewTool == null && ViewTool.PDFViewer == null)
+            {
+                return false;
+            }
+
+            if (isFill)
+            {
+                IsFillMode = InsertFillLayer();
+                if (IsFillMode)
+                {
+                    HideCursor();
+                }
+                FillCreator?.Draw();
+                return IsFillMode;
+            }
+            ShowCursor();
+            if (FillCreator == null)
+            {
+                return true;
+            }
+
+            CPDFViewer pdfViewer = ViewTool.PDFViewer;
+            pdfViewer.RemoveView(FillCreator);
+            FillCreator = null;
+            ViewIndex = -1;
+            FillParam = null;
+
+            return true;
+        }
+
+        public void ClearFillMode()
+        {
+            EnableFillMode(false);
+            ClearFillItem();
+        }
+
+        public void ClearFillItem()
+        {
+            Items?.Clear();
+        }
+
+        public void SetFillParam(FillItem param)
+        {
+            FillParam = param;
+            FillCreator?.SetFillParam(FillParam);
+        }
+
+        private bool IsNeedProcess()
+        {
+            if (IsFillMode == false || FillParam == null || FillCreator == null)
+            {
+                return false;
+            }
+
+            List<FillType> allowType = new List<FillType>()
+            {
+                FillType.Circle,
+                FillType.Square,
+                FillType.Line,
+                FillType.Check,
+                FillType.Cross
+            };
+
+            if (allowType.Contains(FillParam.Type) == false)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        private bool IsMouseOnHitAnnot()
+        {
+            if (ViewTool != null && ViewTool.cacheHitTestAnnot != null)
+            {
+                BaseAnnot cacheAnnot = ViewTool.cacheHitTestAnnot;
+                BaseAnnot baseAnnot = ViewTool.PDFViewer.AnnotHitTest(false);
+                if (baseAnnot != null && baseAnnot.CurrentType != C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
+                {
+                    AnnotData cacheData = cacheAnnot.GetAnnotData();
+                    AnnotData data = baseAnnot.GetAnnotData();
+                    if (data.PageIndex == cacheData.PageIndex && data.AnnotIndex == cacheData.AnnotIndex)
+                    {
+                        return true;
+                    }
+                }
+
+                Point point = Mouse.GetPosition(ViewTool);
+                // PointControlType pointControlType = ViewTool.GetLastSelectedRect().GetHitControlIndex(point);
+                //if (pointControlType != PointControlType.None)
+                //{
+                //    return true;
+                //}
+            }
+            return false;
+        }
+        private bool IsFillHitProcess()
+        {
+            if (IsFillMode)
+            {
+                BaseAnnot oldAnnot = ViewTool.cacheHitTestAnnot;
+                ViewTool.cacheHitTestAnnot = null;
+                ViewTool.isDrawSelectRect = false;
+                BaseAnnot baseAnnot = ViewTool.PDFViewer.AnnotHitTest(true);
+                if (baseAnnot != null && baseAnnot.CurrentType != C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
+                {
+                    ViewTool.cacheHitTestAnnot = baseAnnot;
+                    ViewTool.isDrawSelectRect = true;
+                    List<C_ANNOTATION_TYPE> list = new List<C_ANNOTATION_TYPE>()
+                    {
+                        C_ANNOTATION_TYPE.C_ANNOTATION_LINE,
+                        C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE,
+                        C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON,
+                    };
+                    MouseEventObject eventObj = new MouseEventObject();
+
+                    if (list.Contains(baseAnnot.CurrentType))
+                    {
+                        ViewTool.SetEditAnnotObject();
+                        ViewTool.DrawEditAnnotLayer();
+                        eventObj.IsMersured = baseAnnot.GetAnnotData().Annot.IsMeasured();
+                    }
+                    else
+                    {
+                        ViewTool.SelectedAnnot();
+                    }
+                    eventObj.annotType = baseAnnot.CurrentType;
+                    eventObj.hitTestType = MouseHitTestType.Annot;
+                    ViewTool.DrawSelectedLayer();
+                    ViewTool.InvokeMouseLeftDown(eventObj);
+
+                    return true;
+                }
+
+                if (oldAnnot != null)
+                {
+                    ViewTool.CleanSelectedRect();
+                    MouseEventObject eventObj = new MouseEventObject();
+                    eventObj.annotType = C_ANNOTATION_TYPE.C_ANNOTATION_NONE;
+                    eventObj.hitTestType = MouseHitTestType.Unknown;
+                    ViewTool.InvokeMouseLeftDown(eventObj);
+                    HideCursor();
+                }
+            }
+            return false;
+        }
+
+        private void HideCursor()
+        {
+            if (ViewTool != null && ViewTool.PDFViewer != null)
+            {
+                CPDFViewer pdfViewer = ViewTool.PDFViewer;
+                if (pdfViewer.Cursor != Cursors.None)
+                {
+                    pdfViewer.Cursor = Cursors.None;
+                    ViewTool.Cursor = Cursors.None;
+                }
+            }
+        }
+
+        private void ShowCursor()
+        {
+            if (ViewTool != null && ViewTool.PDFViewer != null)
+            {
+                CPDFViewer pdfViewer = ViewTool.PDFViewer;
+                if (pdfViewer.Cursor == Cursors.None)
+                {
+                    pdfViewer.Cursor = Cursors.Arrow;
+                    ViewTool.Cursor = Cursors.Arrow;
+                }
+            }
+        }
+
+        internal bool MouseDownHandle(MouseButtonEventArgs e)
+        {
+            if (ViewTool != null && ViewTool.cacheHitTestAnnot != null && ViewTool.DrawSelectRectDownEvent())
+            {
+                return false;
+            }
+
+            if (IsFillHitProcess())
+            {
+                FillCreator.CleanDraw();
+                return false;
+            }
+
+            if (IsNeedProcess())
+            {
+                ViewTool.PDFViewer.EnableZoom(false);
+                ViewTool.PDFViewer.CanHorizontallyScroll = false;
+                ViewTool.PDFViewer.CanVerticallyScroll = false;
+                ViewTool.PDFViewer.CaptureMouse();
+                FillCreator.MouseDownPos = e.GetPosition(ViewTool.PDFViewer);
+                FillCreator.CurrentMousePos = FillCreator.MouseDownPos;
+                ViewTool.PDFViewer.GetPointPageInfo(FillCreator.MouseDownPos, out int pageIndex, out Rect paintRect, out Rect pageBound);
+                FillCreator.PageIndex = pageIndex;
+                FillCreator.PageBound = pageBound;
+                FillCreator.IsMouseMoved = false;
+
+                return true;
+            }
+
+            return false;
+        }
+
+        internal bool MouseUpHandle(MouseButtonEventArgs e)
+        {
+            if (ViewTool != null && ViewTool.cacheHitTestAnnot != null)
+            {
+                return false;
+            }
+
+            if (IsNeedProcess())
+            {
+                FillItem annotItem = FillCreator.SaveFillItem();
+
+                ViewTool.PDFViewer.EnableZoom(true);
+                ViewTool.PDFViewer.CanHorizontallyScroll = true;
+                ViewTool.PDFViewer.CanVerticallyScroll = true;
+                ViewTool.PDFViewer.ReleaseMouseCapture();
+
+                if (annotItem != null)
+                {
+                    if (Items.ContainsKey(annotItem.PageIndex) == false)
+                    {
+                        Items[annotItem.PageIndex] = new List<FillItem> { annotItem };
+                    }
+                    Items[annotItem.PageIndex].Add(annotItem);
+                    ViewTool.PDFViewer.UpdateAnnotFrame();
+
+                    FillCreator.MouseDownPos = new Point(-1, -1);
+                    FillCreator.CurrentMousePos = FillCreator.MouseDownPos;
+                    FillCreator.PageIndex = -1;
+                    FillCreator.PageBound = Rect.Empty;
+                    FillCreator.IsMouseMoved = false;
+
+                    FillCreator.CleanDraw();
+                }
+                return true;
+            }
+
+            return false;
+        }
+
+        internal bool MouseMoveHandle(MouseEventArgs e)
+        {
+            if (ViewTool != null && ViewTool.cacheHitTestAnnot != null)
+            {
+                if (e.LeftButton == MouseButtonState.Pressed || ViewTool.DrawSelectRectDownEvent())
+                {
+                    FillCreator?.CleanDraw();
+                    return false;
+                }
+            }
+
+            if (IsNeedProcess())
+            {
+                HideCursor();
+                FillCreator.IsMouseMoved = (e.LeftButton == MouseButtonState.Pressed);
+                FillCreator.CurrentMousePos = e.GetPosition(ViewTool.PDFViewer);
+                FillCreator.Draw();
+                return true;
+            }
+
+            return false;
+        }
+    }
+}