Bläddra i källkod

ComPDFKit.Tools - 旋转框绘制

liuaoran 5 månader sedan
förälder
incheckning
0fcc887bc8

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

@@ -477,6 +477,11 @@ namespace ComPDFKit.Tool
                 Rect rect = DpiHelper.StandardRectToPDFRect(rect1);
                 CRect cRect = new CRect((float)rect.Left, (float)rect.Bottom, (float)rect.Right, (float)rect.Top);
                 e.annotData.Annot.SetRect(cRect);
+                if(e.annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_STAMP)
+                {
+                    // Test
+                    (e.annotData.Annot as CPDFStampAnnotation).SetRotation(45);
+                }
             }
 
             switch (e.annotData.AnnotType)
@@ -1917,7 +1922,7 @@ namespace ComPDFKit.Tool
                         viewerTool.DrawMoveEditAnnot();
                     }
                     else
-                    {
+                    { 
                         if (e.annotType != C_ANNOTATION_TYPE.C_ANNOTATION_LINK)
                         {
                             bool tag = viewerTool.DrawMoveSelectedRect();
@@ -2338,7 +2343,7 @@ namespace ComPDFKit.Tool
                                     case PointControlType.RightTop:
                                         viewerTool.PDFViewer.Cursor = viewerTool.Cursor = Cursors.SizeNESW;
                                         break;
-                                    case PointControlType.MiddlBottom:
+                                    case PointControlType.MiddleBottom:
                                     case PointControlType.MiddleTop:
                                         viewerTool.PDFViewer.Cursor = viewerTool.Cursor = Cursors.SizeNS;
                                         break;

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

@@ -1694,7 +1694,7 @@ namespace ComPDFKit.Tool
                 case PointControlType.RightTop:
                     return Cursors.SizeNESW;
 
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                 case PointControlType.MiddleTop:
                     return Cursors.SizeNS;
 

+ 1 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs

@@ -65,6 +65,7 @@ namespace ComPDFKit.Tool
 
     public partial class CPDFViewerTool : UserControl
     {
+        public Cursor RotationCursor;
         public bool IsDocumentModified
         {
             get => isDocumentModified;

+ 8 - 5
Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj

@@ -203,16 +203,14 @@
     </Page>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
-      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+    <ProjectReference Include="..\..\..\..\ComPDFKit-ForRebuild\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
+      <Project>{122caf49-dcf7-49b1-8872-80b363e187e4}</Project>
       <Name>ComPDFKit.NET</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\..\compdfkit_windows_rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+    <ProjectReference Include="..\..\..\..\ComPDFKit-Rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
       <Project>{783263cf-0da3-4095-9df8-2c4a6b3ff908}</Project>
       <Name>ComPDFKit.Viewer</Name>
     </ProjectReference>
-  </ItemGroup>
-  <ItemGroup>
     <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
       <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
       <Name>ComPDFKit.NET</Name>
@@ -232,5 +230,10 @@
       <Name>ComPDFKit.Viewer</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resource\Cursor\Rotation.cur">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </EmbeddedResource>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>

+ 6 - 6
Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs

@@ -671,7 +671,7 @@ namespace ComPDFKit.Tool.DrawTool
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
                     break;
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     break;
                 case PointControlType.RightBottom:
@@ -824,7 +824,7 @@ namespace ComPDFKit.Tool.DrawTool
             ignorePoints.Add(PointControlType.LeftTop);
             ignorePoints.Add(PointControlType.LeftMiddle);
             ignorePoints.Add(PointControlType.LeftBottom);
-            ignorePoints.Add(PointControlType.MiddlBottom);
+            ignorePoints.Add(PointControlType.MiddleBottom);
             ignorePoints.Add(PointControlType.RightBottom);
             ignorePoints.Add(PointControlType.RightMiddle);
             ignorePoints.Add(PointControlType.RightTop);
@@ -840,7 +840,7 @@ namespace ComPDFKit.Tool.DrawTool
             ignorePoints.Add(PointControlType.LeftTop);
             ignorePoints.Add(PointControlType.LeftMiddle);
             ignorePoints.Add(PointControlType.LeftBottom);
-            ignorePoints.Add(PointControlType.MiddlBottom);
+            ignorePoints.Add(PointControlType.MiddleBottom);
             ignorePoints.Add(PointControlType.RightBottom);
             ignorePoints.Add(PointControlType.RightMiddle);
             ignorePoints.Add(PointControlType.RightTop);
@@ -923,7 +923,7 @@ namespace ComPDFKit.Tool.DrawTool
                         TmpDown = TmpUp + rectMinHeight;
                     }
                     break;
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                     TmpLeft = cacheRect.Left;
                     TmpRight = cacheRect.Right;
                     TmpUp = cacheRect.Top;
@@ -1049,7 +1049,7 @@ namespace ComPDFKit.Tool.DrawTool
                     case PointControlType.RightMiddle:
                         offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? -1 : 1));
                         break;
-                    case PointControlType.MiddlBottom:
+                    case PointControlType.MiddleBottom:
                         offsetPos = new Point(Math.Abs(movePoint.Y) * ratioY * (movePoint.Y < 0 ? 1 : -1), movePoint.Y);
                         break;
                     case PointControlType.MiddleTop:
@@ -1306,7 +1306,7 @@ namespace ComPDFKit.Tool.DrawTool
                                 }
                             }
 
-                            if ((PointControlType)i == PointControlType.MiddlBottom)
+                            if ((PointControlType)i == PointControlType.MiddleBottom)
                             {
                                 if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
                                 {

+ 3 - 3
Demo/Examples/ComPDFKit.Tool/DrawTool/PageSelectedRect.cs

@@ -670,7 +670,7 @@ namespace ComPDFKit.Tool.DrawTool
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
                     break;
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     break;
                 case PointControlType.RightBottom:
@@ -801,7 +801,7 @@ namespace ComPDFKit.Tool.DrawTool
                         TmpDown = TmpUp + rectMinHeight;
                     }
                     break;
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                     TmpLeft = cacheRect.Left;
                     TmpRight = cacheRect.Right;
                     TmpUp = cacheRect.Top;
@@ -928,7 +928,7 @@ namespace ComPDFKit.Tool.DrawTool
                     case PointControlType.RightMiddle:
                         offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? -1 : 1));
                         break;
-                    case PointControlType.MiddlBottom:
+                    case PointControlType.MiddleBottom:
                         offsetPos = new Point(Math.Abs(movePoint.Y) * ratioY * (movePoint.Y < 0 ? 1 : -1), movePoint.Y);
                         break;
                     case PointControlType.MiddleTop:

+ 86 - 30
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs

@@ -1,10 +1,12 @@
 using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Tool.Help;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Viewer.Layer;
 using ComPDFKitViewer;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Data;
 using System.Diagnostics;
 using System.Linq;
 using System.Reflection;
@@ -16,6 +18,7 @@ using System.Windows.Controls.Primitives;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Media3D;
+using System.Windows.Shapes;
 using System.Xml.Linq;
 using static ComPDFKit.Tool.Help.ImportWin32;
 using static System.Net.Mime.MediaTypeNames;
@@ -28,14 +31,14 @@ namespace ComPDFKit.Tool.DrawTool
         LeftTop,
         LeftMiddle,
         LeftBottom,
-        MiddlBottom,
+        MiddleBottom,
         RightBottom,
         RightMiddle,
         RightTop,
-        MiddleTop,
-        Rotate,
+        MiddleTop, 
         Body,
-        Line
+        Line, 
+        Rotate
     }
 
     public enum SelectedType
@@ -49,14 +52,15 @@ namespace ComPDFKit.Tool.DrawTool
     public enum DrawPointType
     {
         Circle,
-        Square,
-        Crop
+        Square, 
+        Crop, 
     }
 
     public enum DrawMoveType
     {
         kDefault,
         kReferenceLine,
+        kRotatable
     }
 
     public class SelectedAnnotData
@@ -73,10 +77,11 @@ namespace ComPDFKit.Tool.DrawTool
 
         public AnnotData annotData { get; set; }
 
+        public double rotationAngle { get; set; }
     }
 
     public partial class SelectedRect : DrawingVisual
-    {
+    { 
         /// <summary>
         /// Re-layout child elements
         /// </summary>
@@ -126,6 +131,8 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected bool isSelected = false;
 
+        protected bool canRotation = false;
+
         protected SelectedType selectedType = SelectedType.None;
 
         public SelectedType GetSelectedType()
@@ -177,13 +184,22 @@ namespace ComPDFKit.Tool.DrawTool
                 {
                     hitControlType = GetHitCropControlIndex(downPoint);
                 }
-                else
+                else 
                 {
                     hitControlType = GetHitControlIndex(downPoint);
                 }
+
                 if (hitControlType != PointControlType.None)
                 {
                     cacheRect = drawRect;
+                    if(hitControlType != PointControlType.Rotate)
+                    {
+                        isInScaling = true;
+                    }
+                    else
+                    {
+                        isInRotate = true;
+                    }
                 }
             }
         }
@@ -193,6 +209,8 @@ namespace ComPDFKit.Tool.DrawTool
             if (isMouseDown && hitControlType != PointControlType.None)
             {
                 isMouseDown = false;
+                isInScaling = false;
+                isInRotate = false;
                 cacheRect = SetDrawRect = drawRect;
                 Draw();
                 if ((int)upPoint.X != (int)mouseDownPoint.X || (int)upPoint.Y != (int)mouseDownPoint.Y)
@@ -223,7 +241,7 @@ namespace ComPDFKit.Tool.DrawTool
         }
 
         public Cursor GetCursor(Point downPoint, Cursor cursor)
-        {
+        { 
             if (isMouseDown)
             {
                 return cursor;
@@ -233,23 +251,22 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 case PointControlType.LeftTop:
                 case PointControlType.RightBottom:
-                    return Cursors.SizeNWSE;
-
+                    return Cursors.SizeNWSE; 
                 case PointControlType.LeftMiddle:
                 case PointControlType.RightMiddle:
-                    return Cursors.SizeWE;
-
+                    return Cursors.SizeWE; 
                 case PointControlType.LeftBottom:
                 case PointControlType.RightTop:
                     return Cursors.SizeNESW;
-
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                 case PointControlType.MiddleTop:
                     return Cursors.SizeNS;
                 case PointControlType.Body:
                     return Cursors.Arrow;
                 case PointControlType.Line:
                     return Cursors.SizeAll;
+                case PointControlType.Rotate:
+                    return CommonHelper.RotationCursor;
                 default:
                     return Cursors.Arrow;
             }
@@ -299,8 +316,10 @@ namespace ComPDFKit.Tool.DrawTool
                 SolidColorBrush solidColorBrush = DrawParam.AnnotRectFillBrush;
                 Pen pen = DrawParam.AnnotRectLinePen;
                 GetBrushAndPen(ref solidColorBrush, ref pen);
+                RotateTransform rotateTransform = new RotateTransform(rotateAngle, centerPoint.X, centerPoint.Y);
+                drawDC.PushTransform(rotateTransform); 
                 drawDC?.DrawRectangle(solidColorBrush, pen, currentRect);
-
+                drawDC.Pop();
                 SolidColorBrush PointBrush = DrawParam.AnnotPointBorderBrush;
                 Pen PointPen = DrawParam.AnnotPointPen;
                 GetPointBrushAndPen(ref PointBrush, ref PointPen);
@@ -310,16 +329,14 @@ namespace ComPDFKit.Tool.DrawTool
                     case DrawPointType.Circle:
                         if (selectedType == SelectedType.PDFEdit)
                         {
-                            DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
-
-                            //DrawEditSelectionBox(drawDC, PointPen);
+                            DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);  
                         }
                         else
                         {
                             DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
                         }
                         break;
-                    case DrawPointType.Square:
+                    case DrawPointType.Square: 
                         DrawSquarePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
                         break;
                     case DrawPointType.Crop:
@@ -330,7 +347,7 @@ namespace ComPDFKit.Tool.DrawTool
                 drawDC = null;
             });
         }
-
+          
         private void GetMoveBrushAndPen(ref SolidColorBrush colorBrush, ref Pen pen)
         {
             switch (selectedType)
@@ -340,7 +357,7 @@ namespace ComPDFKit.Tool.DrawTool
                 case SelectedType.Annot:
                     colorBrush = DrawParam.AnnotMoveBrush;
                     pen = DrawParam.AnnotMovePen;
-                    break;
+                    break; 
                 case SelectedType.PDFEdit:
                     colorBrush = DrawParam.PDFEditMoveBrush;
                     pen = DrawParam.PDFEditMovePen;
@@ -368,7 +385,8 @@ namespace ComPDFKit.Tool.DrawTool
                     }
                     else if (currentDrawPointType == DrawPointType.Crop)
                     {
-                        colorBrush = DrawParam.SPDFEditCropBorderBrush;//new SolidColorBrush((DrawParam.SPDFEditPointPen.Brush as SolidColorBrush).Color);
+                        colorBrush = DrawParam.SPDFEditCropBorderBrush; 
+                        //new SolidColorBrush((DrawParam.SPDFEditPointPen.Brush as SolidColorBrush).Color);
                         pen = DrawParam.SPDFEditPointPen.Clone();
                         pen.DashStyle = DashStyles.Solid;
                     }
@@ -578,6 +596,7 @@ namespace ComPDFKit.Tool.DrawTool
         {
             SetIgnorePoints(new List<PointControlType>());
             SetIsProportionalScaling(false);
+            SetRoationHandle(false);
             isProportionalScaling = false;
             switch (annotData.AnnotType)
             {
@@ -598,6 +617,7 @@ namespace ComPDFKit.Tool.DrawTool
 
                 case C_ANNOTATION_TYPE.C_ANNOTATION_STAMP:
                     SetIsProportionalScaling(true);
+                    SetRoationHandle(true);
                     break;
 
                 case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
@@ -608,11 +628,16 @@ namespace ComPDFKit.Tool.DrawTool
                     break;
             }
             SetMaxRect(annotData.PaintOffset);
-            SetRect(annotData.PaintRect, annotData.CurrentZoom);
+            SetRect(annotData.PaintRect, annotData.CurrentZoom); 
             selectedRectData = new SelectedAnnotData();
             selectedRectData.annotData = annotData;
         }
 
+        private void SetRoationHandle(bool canRotation)
+        {
+            this.canRotation = canRotation;
+        }
+
         public void SetIsProportionalScaling(bool isProportionalScaling)
         {
             this.isProportionalScaling = isProportionalScaling;
@@ -620,11 +645,11 @@ namespace ComPDFKit.Tool.DrawTool
             if (isProportionalScaling)
             {
                 ignorePoints.Add(PointControlType.LeftMiddle);
-                ignorePoints.Add(PointControlType.MiddlBottom);
+                ignorePoints.Add(PointControlType.MiddleBottom);
                 ignorePoints.Add(PointControlType.RightMiddle);
                 ignorePoints.Add(PointControlType.MiddleTop);
                 ignorePoints.Add(PointControlType.Rotate);
-            }
+            } 
         }
 
         public void SetDrawType(DrawPointType drawType)
@@ -688,7 +713,7 @@ namespace ComPDFKit.Tool.DrawTool
             ignorePoints.Add(PointControlType.LeftTop);
             ignorePoints.Add(PointControlType.LeftMiddle);
             ignorePoints.Add(PointControlType.LeftBottom);
-            ignorePoints.Add(PointControlType.MiddlBottom);
+            ignorePoints.Add(PointControlType.MiddleBottom);
             ignorePoints.Add(PointControlType.RightBottom);
             ignorePoints.Add(PointControlType.RightMiddle);
             ignorePoints.Add(PointControlType.RightTop);
@@ -704,7 +729,7 @@ namespace ComPDFKit.Tool.DrawTool
             ignorePoints.Add(PointControlType.LeftTop);
             ignorePoints.Add(PointControlType.LeftMiddle);
             ignorePoints.Add(PointControlType.LeftBottom);
-            ignorePoints.Add(PointControlType.MiddlBottom);
+            ignorePoints.Add(PointControlType.MiddleBottom);
             ignorePoints.Add(PointControlType.RightBottom);
             ignorePoints.Add(PointControlType.RightMiddle);
             ignorePoints.Add(PointControlType.RightTop);
@@ -799,6 +824,28 @@ namespace ComPDFKit.Tool.DrawTool
                 {
                     Point checkPoint = controlPoints[i];
 
+                    if (canRotation)
+                    {
+                        // Convert the rotation angle from degrees to radians
+                        double angleRad = rotateAngle * Math.PI / 180.0;
+
+                        // Calculate the sine and cosine of the angle
+                        double cosAngle = Math.Cos(angleRad);
+                        double sinAngle = Math.Sin(angleRad);
+
+                        // Translate checkPoint to the origin (centerPoint becomes the origin)
+                        double translatedX = checkPoint.X - centerPoint.X;
+                        double translatedY = checkPoint.Y - centerPoint.Y;
+
+                        // Apply the rotation matrix
+                        double rotatedX = translatedX * cosAngle - translatedY * sinAngle;
+                        double rotatedY = translatedX * sinAngle + translatedY * cosAngle;
+
+                        // Translate the point back to its original position
+                        checkPoint.X = rotatedX + centerPoint.X;
+                        checkPoint.Y = rotatedY + centerPoint.Y;
+                    }
+
                     if (isIgnore && IgnorePointsList.Contains(checkPoint))
                     {
                         continue;
@@ -853,7 +900,7 @@ namespace ComPDFKit.Tool.DrawTool
                                 }
                             }
 
-                            if ((PointControlType)i == PointControlType.MiddlBottom)
+                            if ((PointControlType)i == PointControlType.MiddleBottom)
                             {
                                 if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width/3)
                                 {
@@ -866,12 +913,21 @@ namespace ComPDFKit.Tool.DrawTool
                             }
                             break;
                         case DrawPointType.Square:
-
                             Rect checkRect = new Rect(Math.Max(checkPoint.X - pointSize, 0), Math.Max(checkPoint.Y - pointSize, 0), pointSize * 2, pointSize * 2);
+
                             if (checkRect.Contains(point))
                             {
                                 return (PointControlType)i;
                             }
+                            if (canRotation)
+                            { 
+                                Vector checkVector1 = point - rotationPoint;
+
+                                if (checkVector1.Length < pointSize)
+                                {
+                                    return PointControlType.Rotate;
+                                } 
+                            }
                             break;
 
                         case DrawPointType.Crop:

+ 121 - 28
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Windows;
+using System.Windows.Input;
 using System.Windows.Media;
 
 namespace ComPDFKit.Tool.DrawTool
@@ -27,7 +29,11 @@ namespace ComPDFKit.Tool.DrawTool
         /// <summary>
         /// Current click hit control point.
         /// </summary>
-        protected PointControlType hitControlType { get; set; }
+        protected PointControlType hitControlType
+        {
+            get;
+            set;
+        }
 
         /// <summary>
         /// Mouse down position information.
@@ -39,6 +45,10 @@ namespace ComPDFKit.Tool.DrawTool
         /// </summary>
         protected bool isMouseDown { get; set; }
 
+        protected bool isInRotate { get; set; } = false;
+
+        protected bool isInScaling { get; set; } = false;
+
         /// <summary>
         /// Whether proportional scaling is required.
         /// </summary>
@@ -94,6 +104,12 @@ namespace ComPDFKit.Tool.DrawTool
         /// </summary>
         protected List<Point> controlPoints { get; set; } = new List<Point>();
 
+        protected Point centerPoint = new Point();
+
+        protected Point rotationPoint = new Point();
+
+        protected Point dragRotationPoint = new Point();
+
         /// <summary>
         /// Move offset during movement.
         /// </summary>
@@ -119,6 +135,8 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected double PDFViewerActualHeight { get; set; } = 0;
 
+        protected double rotateAngle { get; set; } = 0;
+
         protected double rectPadding = 6;
 
         protected double currentZoom = 1;
@@ -127,6 +145,7 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected bool disable = false;
 
+
         #endregion
 
         #region Functions
@@ -140,17 +159,22 @@ namespace ComPDFKit.Tool.DrawTool
         protected void CalcControlPoint(Rect currentRect)
         {
             controlPoints.Clear();
-            int centerX = (int)(currentRect.Left + currentRect.Right) / 2;
-            int centerY = (int)(currentRect.Top + currentRect.Bottom) / 2;
+            centerPoint.X = (int)(currentRect.Left + currentRect.Right) / 2;
+            centerPoint.Y = (int)(currentRect.Top + currentRect.Bottom) / 2;
 
             controlPoints.Add(new Point(currentRect.Left, currentRect.Top));
-            controlPoints.Add(new Point(currentRect.Left, centerY));
+            controlPoints.Add(new Point(currentRect.Left, centerPoint.Y));
             controlPoints.Add(new Point(currentRect.Left, currentRect.Bottom));
-            controlPoints.Add(new Point(centerX, currentRect.Bottom));
+            controlPoints.Add(new Point(centerPoint.X, currentRect.Bottom));
             controlPoints.Add(new Point(currentRect.Right, currentRect.Bottom));
-            controlPoints.Add(new Point(currentRect.Right, centerY));
+            controlPoints.Add(new Point(currentRect.Right, centerPoint.Y));
             controlPoints.Add(new Point(currentRect.Right, currentRect.Top));
-            controlPoints.Add(new Point(centerX, currentRect.Top));
+            controlPoints.Add(new Point(centerPoint.X, currentRect.Top));
+
+            if (canRotation)
+            {
+                rotationPoint = new Point(centerPoint.X, currentRect.Top - 30);
+            }
         }
 
         protected List<Point> GetControlPoint(Rect currentRect)
@@ -234,6 +258,11 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 return false;
             }
+            if (hitControlType == PointControlType.Rotate)
+            {
+                return SetRotate(mousePoint);
+            }
+
             if (!isOutSideScaling)
             {
                 return NormalScaling(mousePoint);
@@ -270,6 +299,15 @@ namespace ComPDFKit.Tool.DrawTool
 
             return new Size(width, height);
         }
+        private bool SetRotate(Point mousePoint)
+        {
+            dragRotationPoint = mousePoint;
+            Vector moveVector = (mousePoint - centerPoint);
+
+            rotateAngle = Math.Atan2(moveVector.X, -moveVector.Y) * 180 / Math.PI;
+
+            return false;
+        }
 
         /// <summary>
         /// Draw the algorithm in the form of normal scaling (drag a point, only scale in one direction).
@@ -391,7 +429,7 @@ namespace ComPDFKit.Tool.DrawTool
                         }
                         break;
 
-                    case PointControlType.MiddlBottom:
+                    case PointControlType.MiddleBottom:
                         {
                             left = cacheRect.Left;
                             right = cacheRect.Right;
@@ -683,7 +721,7 @@ namespace ComPDFKit.Tool.DrawTool
                         }
                         break;
 
-                    case PointControlType.MiddlBottom:
+                    case PointControlType.MiddleBottom:
                         {
                             left = cacheRect.Left;
                             right = cacheRect.Right;
@@ -905,7 +943,7 @@ namespace ComPDFKit.Tool.DrawTool
                     case PointControlType.RightMiddle:
                         offsetPos = new Point(movePoint.X, Math.Abs(movePoint.X) * ratioX * (movePoint.X < 0 ? -1 : 1));
                         break;
-                    case PointControlType.MiddlBottom:
+                    case PointControlType.MiddleBottom:
                         offsetPos = new Point(Math.Abs(movePoint.Y) * ratioY * (movePoint.Y < 0 ? 1 : -1), movePoint.Y);
                         break;
                     case PointControlType.MiddleTop:
@@ -988,36 +1026,82 @@ namespace ComPDFKit.Tool.DrawTool
         /// </param>
         protected void DrawSquarePoint(DrawingContext drawingContext, List<PointControlType> ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
         {
-            GeometryGroup controlGroup = new GeometryGroup();
-            controlGroup.FillRule = FillRule.Nonzero;
-            List<Point> ignorePointsList = new List<Point>();
-            // Get specific points
-            foreach (PointControlType type in ignoreList)
+
+            RotateTransform rotateTransform = new RotateTransform(rotateAngle, centerPoint.X, centerPoint.Y);
+            if (canRotation && !isInScaling)
             {
-                if ((int)type < controlPoints.Count)
+                Point currentRotationPoint = isInRotate ? dragRotationPoint : rotationPoint;
+                GeometryGroup rotateGroup = new GeometryGroup();
+
+                double angleInRadians = rotateAngle * (Math.PI / 180);
+
+                double sinValue = Math.Sin(angleInRadians);
+                double cosValue = Math.Cos(angleInRadians);
+
+                double rotatedX = currentRotationPoint.X - pointSize * sinValue;
+                double rotatedY = currentRotationPoint.Y + pointSize * cosValue;
+
+                LineGeometry moveLineGeometry = new LineGeometry(centerPoint, new Point(rotatedX, rotatedY));
+
+                EllipseGeometry ellipseGeometry = new EllipseGeometry(currentRotationPoint, PointSize, pointSize);
+
+                rotateGroup.Children.Add(moveLineGeometry);
+                rotateGroup.Children.Add(ellipseGeometry);
+
+                if (!isInRotate)
                 {
-                    ignorePointsList.Add(controlPoints[(int)type]);
+                    rotateGroup.Children.Remove(moveLineGeometry);
+                    LineGeometry stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X, currentRotationPoint.Y + pointSize));
+                    rotateGroup.Children.Add(stopLineGeometry);
+                    drawingContext.PushTransform(rotateTransform);
+                }
+
+                drawingContext?.DrawGeometry(BorderBrush, PointPen, rotateGroup);
+
+                if (!isInRotate)
+                {
+
+                    drawingContext.Pop();
                 }
             }
-            for (int i = 0; i < controlPoints.Count; i++)
+            if (!isInRotate)
             {
-                Point controlPoint = controlPoints[i];
-                if (ignorePointsList.Contains(controlPoint))
+                GeometryGroup controlGroup = new GeometryGroup();
+                controlGroup.FillRule = FillRule.Nonzero;
+                List<Point> ignorePointsList = new List<Point>();
+                // Get specific points
+                foreach (PointControlType type in ignoreList)
                 {
-                    continue;
+                    if ((int)type < controlPoints.Count)
+                    {
+                        ignorePointsList.Add(controlPoints[(int)type]);
+                    }
                 }
-                RectangleGeometry rectPoint = new RectangleGeometry(new Rect(controlPoint.X - PointSize, controlPoint.Y - PointSize,
-                    PointSize * 2, PointSize * 2), 1, 1);
-                controlGroup.Children.Add(rectPoint);
+                for (int i = 0; i < controlPoints.Count; i++)
+                {
+                    Point controlPoint = controlPoints[i];
+                    if (ignorePointsList.Contains(controlPoint))
+                    {
+                        continue;
+                    }
+                    RectangleGeometry rectPoint = new RectangleGeometry(new Rect(controlPoint.X - PointSize, controlPoint.Y - PointSize,
+                        PointSize * 2, PointSize * 2), 1, 1);
+                    controlGroup.Children.Add(rectPoint);
+                }
+
+                drawingContext.PushTransform(rotateTransform);
+                drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
+                drawingContext.Pop();
             }
-            drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
+
+
         }
 
         protected void DrawCropPoint(DrawingContext drawingContext, List<PointControlType> ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
         {
             //GeometryGroup controlGroup = new GeometryGroup();
             //controlGroup.FillRule = FillRule.Nonzero;
-            clipThickness.Left = (SetDrawRect.Left - drawRect.Left)/currentZoom;
+            clipThickness.Left = (SetDrawRect.Left - drawRect.Left) / currentZoom;
             clipThickness.Top = (SetDrawRect.Top - drawRect.Top) / currentZoom;
             clipThickness.Right = (SetDrawRect.Right - drawRect.Right) / currentZoom;
             clipThickness.Bottom = (SetDrawRect.Bottom - drawRect.Bottom) / currentZoom;
@@ -1055,7 +1139,7 @@ namespace ComPDFKit.Tool.DrawTool
             }
 
             //Bottom Center
-            if (!ignoreList.Contains(PointControlType.MiddlBottom))
+            if (!ignoreList.Contains(PointControlType.MiddleBottom))
             {
                 drawingContext?.DrawRectangle(BorderBrush, null, new Rect((controlCurrentPoints[3].X + controlCurrentPoints[3].X - PointSize * 5) / 2, controlCurrentPoints[3].Y, PointSize * 5, PointSize));
             }
@@ -1122,7 +1206,7 @@ namespace ComPDFKit.Tool.DrawTool
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
                     break;
-                case PointControlType.MiddlBottom:
+                case PointControlType.MiddleBottom:
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
                     break;
                 case PointControlType.RightBottom:
@@ -1140,6 +1224,15 @@ namespace ComPDFKit.Tool.DrawTool
                     drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
                     break;
                 case PointControlType.Rotate:
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(moveRect.Left, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Top), new Point(moveRect.Left, 0));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(moveRect.Right, 0));
+
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(moveRect.Left, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Bottom), new Point(moveRect.Left, PDFViewerActualHeight));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(moveRect.Right, PDFViewerActualHeight));
                     break;
                 case PointControlType.Body:
                 case PointControlType.Line:

+ 19 - 2
Demo/Examples/ComPDFKit.Tool/Help/CommonHelper.cs

@@ -11,11 +11,28 @@ using System.Runtime.Remoting.Messaging;
 using System.Windows.Media.Imaging;
 using System.ComponentModel;
 using ComPDFKit.PDFAnnotation;
+using System.Windows.Input;
+using System.Reflection;
 
 namespace ComPDFKit.Tool.Help
 {
     public static class CommonHelper
     {
+        private static Cursor _rotationCursor = null;
+        public static Cursor RotationCursor
+        {
+            get
+            {
+                if (_rotationCursor == null)
+                {
+                    var assembly = Assembly.GetExecutingAssembly();
+                    Stream stream = assembly.GetManifestResourceStream("ComPDFKit.Tool.Resource.Cursor.Rotation.cur");
+                    _rotationCursor = new Cursor(stream);
+                }
+                return _rotationCursor;
+            }
+        }
+
         /// <summary>
         /// Find the parent control of the target type of the object
         /// </summary>
@@ -87,7 +104,7 @@ namespace ComPDFKit.Tool.Help
         public static List<childItem> FindVisualChildList<childItem>(DependencyObject obj)
             where childItem : DependencyObject
         {
-            List <childItem> children = new List <childItem>();
+            List<childItem> children = new List<childItem>();
             try
             {
                 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
@@ -167,7 +184,7 @@ namespace ComPDFKit.Tool.Help
 
         public static void UpdateStickyAP(CPDFTextAnnotation textAnnotation)
         {
-            if(textAnnotation==null || textAnnotation.IsValid()==false)
+            if (textAnnotation == null || textAnnotation.IsValid() == false)
             {
                 return;
             }

BIN
Demo/Examples/ComPDFKit.Tool/Resource/Cursor/Rotation.cur