using ComPDFKit.Import; using ComPDFKit.Measure; using ComPDFKit.PDFAnnotation; using ComPDFKit.PDFDocument; using ComPDFKit.PDFPage; using ComPDFKit.Tool.Help; using ComPDFKit.Tool.SettingParam; using ComPDFKit.Tool.UndoManger; using ComPDFKit.Viewer.Helper; using ComPDFKit.Viewer.Layer; using ComPDFKitViewer; using ComPDFKitViewer.Annot; using ComPDFKitViewer.BaseObject; using ComPDFKitViewer.Helper; using ComPDFKitViewer.Layer; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Annotations; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Media3D; using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper; using static ComPDFKit.Tool.Help.ImportWin32; namespace ComPDFKit.Tool.DrawTool { internal class CreateAnnotTool : CustomizeLayer { public event EventHandler UpdateAnnotHandler; public event EventHandler CreateFreetextCanceled; public event EventHandler MeasureChanged; public static DependencyProperty PopupTextAttachDataProperty = DependencyProperty.Register("PopupTextAttachData", typeof(CPDFAnnotation), typeof(CPDFViewerTool)); #region Attributes /// /// Indicates whether proportional scaling is required /// protected bool isProportionalScaling { get; set; } = false; /// /// Mouse start point /// protected Point mouseStartPoint { get; set; } /// /// Mouse end point /// protected Point mouseEndPoint { get; set; } /// /// Crop point /// protected Point cropPoint { get; set; } /// ///Is drawing annotation /// protected bool isDrawAnnot { get; set; } /// /// Current zoom factor /// private double zoomFactor { get; set; } = 1; /// /// Draw rectangle /// protected Rect drawRect { get; set; } /// /// The rectangle representing the maximum drawing area /// protected Rect maxRect { get; set; } /// /// The rectangle representing the original page range (calculated offset in continuous mode) /// protected Rect pageBound { get; set; } /// /// The rectangle at standard DPI (without subtracting half of the pen thickness) /// protected Rect DPIRect { get; set; } /// /// The offset value during movement /// protected Point moveOffset { get; set; } = new Point(0, 0); protected DrawingContext drawDC { get; set; } protected CPDFAnnotation cPDFAnnotation { get; set; } protected CPDFViewer cPDFViewer { get; set; } protected List inkDrawPoints = new List(); /// /// The collection of points measured for annotation drawing /// protected PointCollection drawPoints { get; set; } = new PointCollection(); protected double textPadding { get; set; } = 10; protected Border lastTextBorder; protected TextBox lastTextui; protected Point freeTextPoint { get; set; } protected MeasureSetting measureSetting = new MeasureSetting(); protected DefaultDrawParam defaultDrawParam = new DefaultDrawParam(); protected DefaultSettingParam defaultSettingParam = new DefaultSettingParam(); #endregion public CreateAnnotTool(MeasureSetting setting, DefaultDrawParam drawParam, DefaultSettingParam settingParam) { measureSetting = setting; defaultDrawParam = drawParam; defaultSettingParam = settingParam; } public Point GetStartPoint() { return DpiHelper.StandardPointToPDFPoint(new Point((mouseStartPoint.X - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (mouseStartPoint.Y - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor)); } public Point GetEndPoint() { if (moveOffset == new Point()) { return new Point(-1, -1); } else { return DpiHelper.StandardPointToPDFPoint(new Point((mouseEndPoint.X - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (mouseEndPoint.Y - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor)); } } public double GetMoveLength() { if (mouseEndPoint == new Point()) { return 0; } Point checkPoint = mouseEndPoint; checkPoint.X = Math.Max(pageBound.Left, checkPoint.X); checkPoint.X = Math.Min(pageBound.Right, checkPoint.X); checkPoint.Y = Math.Max(pageBound.Top, checkPoint.Y); checkPoint.Y = Math.Min(pageBound.Bottom, checkPoint.Y); Vector moveOffset = checkPoint - mouseStartPoint; return moveOffset.Length; } public List GetInkDrawPoints() { List points = new List { new Point((mouseStartPoint.X - pageBound.Left+(cropPoint.X*zoomFactor)) / zoomFactor, (mouseStartPoint.Y - pageBound.Top + (cropPoint.Y*zoomFactor)) / zoomFactor) }; foreach (Point item in inkDrawPoints) { points.Add(new Point((item.X - pageBound.Left + (cropPoint.X * zoomFactor)) / zoomFactor, (item.Y - pageBound.Top + (cropPoint.Y * zoomFactor)) / zoomFactor)); } return points; } public List GetMeasureDrawPoints() { List points = new List(); foreach (Point item in drawPoints) { points.Add(new Point((item.X - pageBound.Left + (cropPoint.X * zoomFactor)) / zoomFactor, (item.Y - pageBound.Top + (cropPoint.Y * zoomFactor)) / zoomFactor)); } if (defaultSettingParam.IsCreateSquarePolygonMeasure) { if (points.Count == 2) { Rect rect = new Rect(points[0], points[1]); points.Clear(); points.Add(rect.TopLeft); points.Add(rect.BottomLeft); points.Add(rect.BottomRight); points.Add(rect.TopRight); } else if (points.Count == 1) { Rect checkRect = pageBound; // Current drawing during the movement process. Point checkPoint = mouseEndPoint; checkPoint.X = Math.Max(checkRect.Left, checkPoint.X); checkPoint.X = Math.Min(checkRect.Right, checkPoint.X); checkPoint.Y = Math.Max(checkRect.Top, checkPoint.Y); checkPoint.Y = Math.Min(checkRect.Bottom, checkPoint.Y); List drawPointsList = new List { new Point((drawPoints[0].X - pageBound.Left + (cropPoint.X * zoomFactor)) / zoomFactor, (drawPoints[0].Y - pageBound.Top + (cropPoint.Y * zoomFactor)) / zoomFactor), new Point((checkPoint.X - pageBound.Left + (cropPoint.X * zoomFactor)) / zoomFactor, (checkPoint.Y - pageBound.Top + (cropPoint.Y * zoomFactor)) / zoomFactor) }; Rect rect = new Rect(drawPointsList[0], drawPointsList[1]); points.Clear(); points.Add(rect.TopLeft); points.Add(rect.BottomLeft); points.Add(rect.BottomRight); points.Add(rect.TopRight); } } return points; } public void SetIsProportionalScaling(bool isOpen) { isProportionalScaling = isOpen; } #region Draw public CPDFAnnotation StartDraw(Point downPoint, Point cropPoint, CPDFPage cPDFPage, Rect maxRect, Rect pageBound, C_ANNOTATION_TYPE annotType, CPDFViewer viewer, double zoom) { RemoveTextBox(); mouseStartPoint = downPoint; isDrawAnnot = true; this.maxRect = maxRect; zoomFactor = zoom; moveOffset = new Point(); int newIndex = cPDFPage.GetAnnotCount(); cPDFAnnotation = cPDFPage.CreateAnnot(annotType); if (cPDFAnnotation != null) { cPDFAnnotation.SetCreationDate(PDFHelp.GetCurrentPdfTime()); cPDFAnnotation.SetModifyDate(PDFHelp.GetCurrentPdfTime()); List annotList = cPDFPage.GetAnnotations(); cPDFAnnotation = annotList[newIndex]; cPDFViewer = viewer; drawPoints.Add(downPoint); this.cropPoint = cropPoint; this.pageBound = pageBound; DPIRect = new Rect(); if (annotType != C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON) { defaultSettingParam.IsCreateSquarePolygonMeasure = false; } } return cPDFAnnotation; } public void MoveDraw(Point downPoint, double zoom) { if (isDrawAnnot) { moveOffset = new Point( mouseEndPoint.X - downPoint.X, mouseEndPoint.Y - downPoint.Y ); mouseEndPoint = downPoint; zoomFactor = zoom; Draw(); } } public Rect EndDraw() { if (isDrawAnnot) { if (cPDFAnnotation != null && cPDFAnnotation.Type == C_ANNOTATION_TYPE.C_ANNOTATION_TEXT) { if (DPIRect.Equals(new Rect())) { DPIRect = drawRect = new Rect(mouseStartPoint.X, mouseStartPoint.Y, 32 * zoomFactor, 32 * zoomFactor); } else { DPIRect = drawRect = new Rect(mouseEndPoint.X, mouseEndPoint.Y, 32 * zoomFactor, 32 * zoomFactor); } } Rect StandardRect = new Rect( (DPIRect.Left - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (DPIRect.Top - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor, DPIRect.Width / zoomFactor, DPIRect.Height / zoomFactor); isDrawAnnot = false; freeTextPoint = new Point((mouseStartPoint.X - pageBound.X) / zoomFactor, (mouseStartPoint.Y - pageBound.Y) / zoomFactor); mouseStartPoint = new Point(); mouseEndPoint = new Point(); moveOffset = new Point(); pageBound = new Rect(); DPIRect = new Rect(); cPDFAnnotation = null; inkDrawPoints.Clear(); drawPoints.Clear(); return DpiHelper.StandardRectToPDFRect(StandardRect); } return new Rect(); } public override void Draw() { Dispatcher.Invoke(() => { if (cPDFAnnotation == null) { return; } drawDC = Open(); switch (cPDFAnnotation.Type) { case C_ANNOTATION_TYPE.C_ANNOTATION_TEXT: DPIRect = drawRect = new Rect(mouseStartPoint.X, mouseStartPoint.Y, 32, 32); break; case C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT: DrawText(); break; case C_ANNOTATION_TYPE.C_ANNOTATION_LINE: if ((cPDFAnnotation as CPDFLineAnnotation).IsMeasured()) { DrawLineMeasure(drawDC); } else { DrawLine(drawDC); } break; case C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE: DrawSquare(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE: DrawCircle(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_INK: DrawInk(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_LINK: DrawLink(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON: DrawPolygonMeasure(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE: DrawPolyLineMeasure(drawDC); break; case C_ANNOTATION_TYPE.C_ANNOTATION_REDACT: DrawRedact(drawDC); break; default: break; } Present(); }); } public virtual void ClearDraw() { RemoveTextBox(); Open(); Present(); } private void DrawCircle(DrawingContext drawingContext) { CPDFCircleAnnotation circleAnnot = (cPDFAnnotation as CPDFCircleAnnotation); Pen DrawPen = new Pen(new SolidColorBrush(Color.FromRgb(circleAnnot.LineColor[0], circleAnnot.LineColor[1], circleAnnot.LineColor[2])), (int)Math.Ceiling(circleAnnot.LineWidth / 72 * 96 * zoomFactor)); SolidColorBrush FillBrush = new SolidColorBrush(Colors.Transparent); if (circleAnnot.HasBgColor) { FillBrush = new SolidColorBrush(Color.FromRgb(circleAnnot.BgColor[0], circleAnnot.BgColor[1], circleAnnot.BgColor[2])); } DrawPen.Brush.Opacity = circleAnnot.Transparency / 255D; FillBrush.Opacity = circleAnnot.Transparency / 255D; if (circleAnnot.Dash != null && circleAnnot.Dash.Length > 0 && circleAnnot.LineWidth > 0) { DashStyle dash = new DashStyle(); foreach (var offset in circleAnnot.Dash) { dash.Dashes.Add(offset / circleAnnot.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } if (isProportionalScaling) { Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint); if (mouseOffset.X < 0) { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } } else { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } } } Rect rect = new Rect(mouseStartPoint, mouseEndPoint); double mLeft = rect.Left; double mRight = rect.Right; double mUp = rect.Top; double mDown = rect.Bottom; if (rect.Left < maxRect.Left) { mLeft = maxRect.Left; } if (rect.Right > maxRect.Right) { mRight = maxRect.Right; } if (rect.Top < maxRect.Top) { mUp = maxRect.Top; } if (rect.Bottom > maxRect.Bottom) { mDown = maxRect.Bottom; } DPIRect = drawRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp); double centerX = (drawRect.Left + drawRect.Width / 2); double centerY = (drawRect.Top + drawRect.Height / 2); double radiusX = drawRect.Width / 2 - DrawPen.Thickness; double radiusY = drawRect.Height / 2 - DrawPen.Thickness; if (radiusX <= 0 || radiusY <= 0) { drawingContext.DrawEllipse(DrawPen.Brush, null, new Point(centerX, centerY), (drawRect.Width / 2), (drawRect.Height / 2)); } else { drawingContext?.DrawEllipse(null, DrawPen, new Point(centerX, centerY), radiusX, radiusY); if ((int)(drawRect.Width / 2 - DrawPen.Thickness) > 0 && (int)(drawRect.Height / 2 - DrawPen.Thickness) > 0) { drawingContext?.DrawEllipse(FillBrush, null, new Point(centerX, centerY), (drawRect.Width / 2 - DrawPen.Thickness), (drawRect.Height / 2 - DrawPen.Thickness)); } } } private void DrawSquare(DrawingContext drawingContext) { CPDFSquareAnnotation squareAnnot = (cPDFAnnotation as CPDFSquareAnnotation); Pen DrawPen = new Pen(new SolidColorBrush(Color.FromRgb(squareAnnot.LineColor[0], squareAnnot.LineColor[1], squareAnnot.LineColor[2])), (int)Math.Ceiling(squareAnnot.LineWidth / 72 * 96 * zoomFactor)); SolidColorBrush FillBrush = new SolidColorBrush(Colors.Transparent); if (squareAnnot.HasBgColor) { FillBrush = new SolidColorBrush(Color.FromRgb(squareAnnot.BgColor[0], squareAnnot.BgColor[1], squareAnnot.BgColor[2])); } DrawPen.Brush.Opacity = squareAnnot.Transparency / 255D; FillBrush.Opacity = squareAnnot.Transparency / 255D; if (squareAnnot.Dash != null && squareAnnot.Dash.Length > 0 && squareAnnot.LineWidth > 0) { DashStyle dash = new DashStyle(); foreach (var offset in squareAnnot.Dash) { dash.Dashes.Add(offset / squareAnnot.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } if (isProportionalScaling) { Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint); if (mouseOffset.X < 0) { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } } else { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } } } Rect rect = new Rect(mouseStartPoint, mouseEndPoint); double mLeft = rect.Left; double mRight = rect.Right; double mUp = rect.Top; double mDown = rect.Bottom; if (rect.Left < maxRect.Left) { mLeft = maxRect.Left; } if (rect.Right > maxRect.Right) { mRight = maxRect.Right; } if (rect.Top < maxRect.Top) { mUp = maxRect.Top; } if (rect.Bottom > maxRect.Bottom) { mDown = maxRect.Bottom; } DPIRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp); int halfPenWidth = (int)Math.Ceiling(DrawPen.Thickness / 2); double drawWidth = DPIRect.Width - halfPenWidth * 2; double drawHeight = DPIRect.Height - halfPenWidth * 2; if (drawWidth > 0 && drawHeight > 0) { drawRect = new Rect( (int)DPIRect.Left + halfPenWidth, (int)DPIRect.Top + halfPenWidth, (int)DPIRect.Width - halfPenWidth * 2, (int)DPIRect.Height - halfPenWidth * 2); drawingContext?.DrawRectangle(null, DrawPen, drawRect); halfPenWidth = (int)Math.Floor(DrawPen.Thickness / 2); if (drawRect.Width - halfPenWidth * 2 > 0 && drawRect.Height - halfPenWidth * 2 > 0) { Rect innerRect = new Rect(drawRect.Left + halfPenWidth, drawRect.Top + halfPenWidth, drawRect.Width - 2 * halfPenWidth, drawRect.Height - 2 * halfPenWidth); drawingContext?.DrawRectangle(FillBrush, null, innerRect); } } } private void DrawLine(DrawingContext drawingContext) { CPDFLineAnnotation annotLine = (cPDFAnnotation as CPDFLineAnnotation); Pen DrawPen = new Pen(new SolidColorBrush( Color.FromRgb( annotLine.LineColor[0], annotLine.LineColor[1], annotLine.LineColor[2])), (int)Math.Ceiling(annotLine.LineWidth == 0 ? 0.5 : annotLine.LineWidth * zoomFactor)); DrawPen.Brush.Opacity = annotLine.Transparency / 255D; if (annotLine.Dash != null && annotLine.Dash.Length > 0 && annotLine.LineWidth > 0) { DashStyle dash = new DashStyle(); foreach (var offset in annotLine.Dash) { dash.Dashes.Add(offset / annotLine.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } ArrowHelper drawLine = new ArrowHelper(); if (isProportionalScaling) { mouseEndPoint = CalcAnglePoint(mouseEndPoint, mouseStartPoint, pageBound); DPIRect = new Rect(mouseStartPoint, mouseEndPoint); drawLine.LineStart = mouseStartPoint; drawLine.LineEnd = mouseEndPoint; drawLine.ArrowLength = (uint)Math.Max(DrawPen.Thickness * 3, 12 * zoomFactor); drawLine.StartSharp = annotLine.HeadLineType; drawLine.EndSharp = annotLine.TailLineType; drawingContext.DrawGeometry(null, DrawPen, drawLine.BuildArrowBody()); } else { Point checkPoint = mouseEndPoint; if (mouseEndPoint.X < maxRect.Left) { checkPoint.X = maxRect.Left; } if (mouseEndPoint.X > maxRect.Right) { checkPoint.X = maxRect.Right; } if (mouseEndPoint.Y < maxRect.Top) { checkPoint.Y = maxRect.Top; } if (mouseEndPoint.Y > maxRect.Bottom) { checkPoint.Y = maxRect.Bottom; } mouseEndPoint = checkPoint; DPIRect = new Rect(mouseStartPoint, mouseEndPoint); drawLine.LineStart = mouseStartPoint; drawLine.LineEnd = mouseEndPoint; drawLine.ArrowLength = (uint)Math.Max(DrawPen.Thickness * 3, 12 * zoomFactor); drawLine.StartSharp = annotLine.HeadLineType; drawLine.EndSharp = annotLine.TailLineType; drawingContext.DrawGeometry(null, DrawPen, drawLine.BuildArrowBody()); } } private void DrawInk(DrawingContext drawingContext) { CPDFInkAnnotation annotLine = (cPDFAnnotation as CPDFInkAnnotation); if (annotLine == null || annotLine.IsValid() == false) { return; } byte transparent = annotLine.GetTransparency(); Pen DrawPen = new Pen(new SolidColorBrush(Color.FromArgb(transparent, annotLine.InkColor[0], annotLine.InkColor[1], annotLine.InkColor[2])), annotLine.Thickness * zoomFactor); DrawPen.StartLineCap = PenLineCap.Round; DrawPen.EndLineCap = PenLineCap.Round; PathGeometry pathDraw = new PathGeometry(); Point CurrentPoint = mouseEndPoint; Rect MaxRect = pageBound; if (CurrentPoint.X > MaxRect.Right) { CurrentPoint.X = MaxRect.Right; } if (CurrentPoint.X < MaxRect.Left) { CurrentPoint.X = MaxRect.Left; } if (CurrentPoint.Y > MaxRect.Bottom) { CurrentPoint.Y = MaxRect.Bottom; } if (CurrentPoint.Y < MaxRect.Top) { CurrentPoint.Y = MaxRect.Top; } inkDrawPoints.Add(CurrentPoint); pathDraw.Figures = new PathFigureCollection(); PathFigure pathFigure = new PathFigure(); pathDraw.Figures.Add(pathFigure); pathFigure.StartPoint = mouseStartPoint; foreach (Point addPoint in inkDrawPoints) { LineSegment lineSegment = new LineSegment(addPoint, true); lineSegment.IsSmoothJoin = true; pathFigure.Segments.Add(lineSegment); } Rect checkRect = pageBound; RectangleGeometry rectGeometry = new RectangleGeometry(); drawRect = rectGeometry.Rect = checkRect; drawingContext?.PushClip(rectGeometry); drawingContext?.DrawGeometry(null, DrawPen, pathDraw); } private void DrawLink(DrawingContext drawingContext) { Pen DrawPen = defaultDrawParam.LinkPen; DrawPen.Thickness *= zoomFactor; SolidColorBrush FillBrush = defaultDrawParam.LinkBrush; if (isProportionalScaling) { Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint); if (mouseOffset.X < 0) { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } } else { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } } } Rect rect = new Rect(mouseStartPoint, mouseEndPoint); double mLeft = rect.Left; double mRight = rect.Right; double mUp = rect.Top; double mDown = rect.Bottom; if (rect.Left < maxRect.Left) { mLeft = maxRect.Left; } if (rect.Right > maxRect.Right) { mRight = maxRect.Right; } if (rect.Top < maxRect.Top) { mUp = maxRect.Top; } if (rect.Bottom > maxRect.Bottom) { mDown = maxRect.Bottom; } DPIRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp); int halfPenWidth = (int)Math.Ceiling(DrawPen.Thickness / 2); double drawWidth = DPIRect.Width - halfPenWidth * 2; double drawHeight = DPIRect.Height - halfPenWidth * 2; if (drawWidth > 0 && drawHeight > 0) { drawRect = new Rect( (int)DPIRect.Left + halfPenWidth, (int)DPIRect.Top + halfPenWidth, (int)DPIRect.Width - halfPenWidth * 2, (int)DPIRect.Height - halfPenWidth * 2); drawingContext?.DrawRectangle(null, DrawPen, drawRect); halfPenWidth = (int)Math.Floor(DrawPen.Thickness / 2); if (drawRect.Width - halfPenWidth * 2 > 0 && drawRect.Height - halfPenWidth * 2 > 0) { Rect innerRect = new Rect(drawRect.Left + halfPenWidth, drawRect.Top + halfPenWidth, drawRect.Width - 2 * halfPenWidth, drawRect.Height - 2 * halfPenWidth); drawingContext?.DrawRectangle(FillBrush, null, innerRect); } } } private void DrawRedact(DrawingContext drawingContext) { Pen DrawPen = defaultDrawParam.RedactPen; if (cPDFAnnotation != null && cPDFAnnotation.IsValid() && cPDFAnnotation.Type == C_ANNOTATION_TYPE.C_ANNOTATION_REDACT) { CPDFRedactAnnotation redactAnnot = cPDFAnnotation as CPDFRedactAnnotation; if (redactAnnot.OutlineColor != null && redactAnnot.OutlineColor.Length == 3) { DrawPen = new Pen(new SolidColorBrush(Color.FromRgb(redactAnnot.OutlineColor[0], redactAnnot.OutlineColor[1], redactAnnot.OutlineColor[2])), DrawPen.Thickness); } } SolidColorBrush FillBrush = new SolidColorBrush(Color.FromArgb(0x46, 0x46, 0x82, 0xB4)); if (isProportionalScaling) { Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint); if (mouseOffset.X < 0) { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } } else { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } } } Rect rect = new Rect(mouseStartPoint, mouseEndPoint); double mLeft = rect.Left; double mRight = rect.Right; double mUp = rect.Top; double mDown = rect.Bottom; if (rect.Left < maxRect.Left) { mLeft = maxRect.Left; } if (rect.Right > maxRect.Right) { mRight = maxRect.Right; } if (rect.Top < maxRect.Top) { mUp = maxRect.Top; } if (rect.Bottom > maxRect.Bottom) { mDown = maxRect.Bottom; } DPIRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp); int halfPenWidth = (int)Math.Ceiling(DrawPen.Thickness / 2); double drawWidth = DPIRect.Width - halfPenWidth * 2; double drawHeight = DPIRect.Height - halfPenWidth * 2; if (drawWidth > 0 && drawHeight > 0) { drawRect = new Rect( (int)DPIRect.Left + halfPenWidth, (int)DPIRect.Top + halfPenWidth, (int)DPIRect.Width - halfPenWidth * 2, (int)DPIRect.Height - halfPenWidth * 2); drawingContext?.DrawRectangle(null, DrawPen, drawRect); halfPenWidth = (int)Math.Floor(DrawPen.Thickness / 2); if (drawRect.Width - halfPenWidth * 2 > 0 && drawRect.Height - halfPenWidth * 2 > 0) { Rect innerRect = new Rect(drawRect.Left + halfPenWidth, drawRect.Top + halfPenWidth, drawRect.Width - 2 * halfPenWidth, drawRect.Height - 2 * halfPenWidth); drawingContext?.DrawRectangle(FillBrush, null, innerRect); } } } private void DrawPolyLineMeasure(DrawingContext drawingContext) { CPDFPolylineAnnotation polyLine = (cPDFAnnotation as CPDFPolylineAnnotation); byte[] bytes = polyLine.LineColor; Color color = ParamConverter.ConverterByteForColor(bytes); color.A = polyLine.GetTransparency(); Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth()); SolidColorBrush TextBrush = Brushes.Red; if (polyLine.IsMeasured()) { CPDFPerimeterMeasure measureInfo = polyLine.GetPerimeterMeasure(); if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3) { byte[] fontColor = measureInfo.TextAttribute.FontColor; TextBrush = new SolidColorBrush(Color.FromRgb(fontColor[0], fontColor[1], fontColor[2])); } if (polyLine.Dash != null && polyLine.Dash.Length > 0) { DashStyle dash = new DashStyle(); foreach (var offset in polyLine.Dash) { dash.Dashes.Add(offset / polyLine.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } } if (isProportionalScaling) { if (drawPoints != null && drawPoints.Count > 0) { mouseEndPoint = CalcAnglePoint(mouseEndPoint, drawPoints[drawPoints.Count - 1], pageBound); } } Point checkPoint = mouseEndPoint; checkPoint.X = Math.Max(pageBound.Left, checkPoint.X); checkPoint.X = Math.Min(pageBound.Right, checkPoint.X); checkPoint.Y = Math.Max(pageBound.Top, checkPoint.Y); checkPoint.Y = Math.Min(pageBound.Bottom, checkPoint.Y); if (drawPoints.Count > 0) { PathGeometry drawPath = new PathGeometry(); PathFigure drawFigure = new PathFigure(); drawFigure.StartPoint = drawPoints[0]; PolyLineSegment polySegment = new PolyLineSegment(); for (int i = 1; i < drawPoints.Count; i++) { polySegment.Points.Add(drawPoints[i]); } polySegment.Points.Add(checkPoint); if (polySegment.Points.Count > 0) { drawFigure.Segments.Add(polySegment); } if (drawFigure.Segments.Count > 0) { drawPath.Figures.Add(drawFigure); } double totalInch = 0; if (drawPoints.Count > 1) { for (int i = 0; i < drawPoints.Count - 1; i++) { totalInch += measureSetting.GetMeasureLength(drawPoints[i], drawPoints[i + 1], zoomFactor); } } double currentInch = measureSetting.GetMeasureLength(drawPoints[drawPoints.Count - 1], checkPoint, zoomFactor); totalInch += currentInch; drawingContext?.DrawGeometry(null, DrawPen, drawPath); Point closePoint = drawPoints[drawPoints.Count - 1]; Vector movevector = checkPoint - closePoint; FormattedText moveText = new FormattedText( string.Format("{0} {1}", measureSetting.GetPrecisionData(currentInch), measureSetting.RulerTranslateUnit), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("YaHei"), 16, TextBrush); FormattedText totalText = new FormattedText( string.Format("{0} {1}", measureSetting.GetPrecisionData(totalInch), measureSetting.RulerTranslateUnit), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("YaHei"), 16, TextBrush); if (movevector.Length > moveText.Width + textPadding) { if (checkPoint.X >= closePoint.X) { Point linePoint = new Point(closePoint.X + movevector.Length, closePoint.Y); Point drawPoint = new Point( linePoint.X - moveText.Width - textPadding, linePoint.Y - moveText.Height); Vector anglevector = linePoint - closePoint; RotateTransform transform = new RotateTransform(); transform.CenterX = closePoint.X; transform.CenterY = closePoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); drawingContext?.DrawText(moveText, drawPoint); if (totalInch > currentInch) { drawingContext?.DrawText(totalText, new Point( drawPoint.X + moveText.Width + textPadding * 2, drawPoint.Y )); } drawingContext.Pop(); } else { Point linePoint = new Point(closePoint.X - movevector.Length, closePoint.Y); Point drawPoint = new Point( linePoint.X + textPadding, linePoint.Y - moveText.Height); Vector anglevector = linePoint - closePoint; RotateTransform transform = new RotateTransform(); transform.CenterX = closePoint.X; transform.CenterY = closePoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); drawingContext?.DrawText(moveText, drawPoint); if (totalInch > currentInch) { drawingContext?.DrawText(totalText, new Point( drawPoint.X - totalText.Width - textPadding * 2, drawPoint.Y )); } drawingContext.Pop(); } } double left = drawPoints.AsEnumerable().Select(x => x.X).Min(); double right = drawPoints.AsEnumerable().Select(x => x.X).Max(); double top = drawPoints.AsEnumerable().Select(x => x.Y).Min(); double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max(); DPIRect = new Rect(left, top, right - left, bottom - top); MeasureEventArgs measureEvent = new MeasureEventArgs(); if (drawPoints.Count < 2) { measureEvent.Angle = 0; } else { Vector standVector = drawPoints[drawPoints.Count - 1] - drawPoints[drawPoints.Count - 2]; Vector endvector = closePoint - checkPoint; measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(endvector, standVector)); } measureEvent.RulerTranslateUnit = measureSetting.RulerTranslateUnit; measureEvent.RulerTranslate = measureSetting.RulerTranslate; measureEvent.RulerBase = measureSetting.RulerBase; measureEvent.RulerBaseUnit = measureSetting.RulerBaseUnit; measureEvent.Precision = measureSetting.Precision; measureEvent.Type = CPDFMeasureType.CPDF_PERIMETER_MEASURE; measureEvent.Distance = totalText.Text; MeasureChanged?.Invoke(this, measureEvent); } } private void DrawPolygonMeasure(DrawingContext drawingContext) { CPDFPolygonAnnotation polyLine = (cPDFAnnotation as CPDFPolygonAnnotation); byte[] bytes = polyLine.LineColor; Color color = ParamConverter.ConverterByteForColor(bytes); color.A = polyLine.GetTransparency(); Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth()); Pen EndDrawPen = new Pen(Brushes.Black, polyLine.GetBorderWidth()); SolidColorBrush TextBrush = Brushes.Red; if (polyLine.IsMeasured()) { CPDFAreaMeasure measureInfo = polyLine.GetAreaMeasure(); if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3) { byte[] fontColor = measureInfo.TextAttribute.FontColor; TextBrush = new SolidColorBrush(Color.FromRgb(fontColor[0], fontColor[1], fontColor[2])); } if (polyLine.Dash != null && polyLine.Dash.Length > 0) { DashStyle dash = new DashStyle(); foreach (var offset in polyLine.Dash) { dash.Dashes.Add(offset / polyLine.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } } if (isProportionalScaling) { if (drawPoints != null && drawPoints.Count > 0) { mouseEndPoint = CalcAnglePoint(mouseEndPoint, drawPoints[drawPoints.Count - 1], pageBound); } } Point checkPoint = mouseEndPoint; checkPoint.X = Math.Max(pageBound.Left, checkPoint.X); checkPoint.X = Math.Min(pageBound.Right, checkPoint.X); checkPoint.Y = Math.Max(pageBound.Top, checkPoint.Y); checkPoint.Y = Math.Min(pageBound.Bottom, checkPoint.Y); PointCollection points = drawPoints.Clone(); if (defaultSettingParam.IsCreateSquarePolygonMeasure && drawPoints.Count == 1) { Point star = points[0]; Rect rect = new Rect(star, checkPoint); points.Clear(); points.Add(rect.TopLeft); points.Add(rect.BottomLeft); points.Add(rect.BottomRight); points.Add(rect.TopRight); } if (points.Count > 0) { PathGeometry drawPath = new PathGeometry(); PathFigure drawFigure = new PathFigure(); drawFigure.StartPoint = points[0]; PolyLineSegment polySegment = new PolyLineSegment(); for (int i = 1; i < points.Count; i++) { polySegment.Points.Add(points[i]); } if (defaultSettingParam.IsCreateSquarePolygonMeasure) { polySegment.Points.Add(points[0]); } else { //Add the current point during the movement. polySegment.Points.Add(checkPoint); } if (polySegment.Points.Count > 0) { drawFigure.Segments.Add(polySegment); } if (drawFigure.Segments.Count > 0) { drawPath.Figures.Add(drawFigure); } //Draw the line segment. drawingContext?.DrawGeometry(null, DrawPen, drawPath); //Draw the example line connected by the start point and the end point. if (points.Count > 1) { if (defaultSettingParam.IsCreateSquarePolygonMeasure) { drawingContext?.DrawLine(DrawPen, points[0], polySegment.Points.Last()); } else { drawingContext?.DrawLine(EndDrawPen, points[0], polySegment.Points.Last()); } } //Calculate the length. double totalInch = 0; if (points.Count > 1) { for (int i = 0; i < points.Count - 1; i++) { totalInch += measureSetting.GetMeasureLength(points[i], points[i + 1], zoomFactor); } } double currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], checkPoint, zoomFactor); if (defaultSettingParam.IsCreateSquarePolygonMeasure) { currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], points[0], zoomFactor); } totalInch += currentInch; Point closePoint = points[points.Count - 1]; Vector movevector = checkPoint - closePoint; FormattedText moveText = new FormattedText( string.Format("{0} {1}", measureSetting.GetPrecisionData(currentInch), measureSetting.RulerTranslateUnit), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("YaHei"), 16, TextBrush); FormattedText totalText = new FormattedText( string.Format("{0} {1}", measureSetting.GetPrecisionData(totalInch), measureSetting.RulerTranslateUnit), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("YaHei"), 16, TextBrush); //Judge the text display form. if (movevector.Length > moveText.Width + textPadding || defaultSettingParam.IsCreateSquarePolygonMeasure) { if (checkPoint.X >= closePoint.X) { Point linePoint = new Point(closePoint.X + movevector.Length, closePoint.Y); Point drawPoint = new Point( linePoint.X - moveText.Width - textPadding, linePoint.Y - moveText.Height); Vector anglevector = linePoint - closePoint; RotateTransform transform = new RotateTransform(); transform.CenterX = closePoint.X; transform.CenterY = closePoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); if (!defaultSettingParam.IsCreateSquarePolygonMeasure) { drawingContext?.DrawText(moveText, drawPoint); } if (totalInch > currentInch) { drawingContext?.DrawText(totalText, new Point( drawPoint.X + moveText.Width + textPadding * 2, drawPoint.Y )); } drawingContext.Pop(); } else { Point linePoint = new Point(closePoint.X - movevector.Length, closePoint.Y); Point drawPoint = new Point( linePoint.X + textPadding, linePoint.Y - moveText.Height); Vector anglevector = linePoint - closePoint; RotateTransform transform = new RotateTransform(); transform.CenterX = closePoint.X; transform.CenterY = closePoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); if (!defaultSettingParam.IsCreateSquarePolygonMeasure) { drawingContext?.DrawText(moveText, drawPoint); } if (totalInch > currentInch) { drawingContext?.DrawText(totalText, new Point( drawPoint.X - totalText.Width - textPadding * 2, drawPoint.Y )); } drawingContext.Pop(); } } double left = drawPoints.AsEnumerable().Select(x => x.X).Min(); double right = drawPoints.AsEnumerable().Select(x => x.X).Max(); double top = drawPoints.AsEnumerable().Select(x => x.Y).Min(); double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max(); DPIRect = new Rect(left, top, right - left, bottom - top); if (defaultSettingParam.IsCreateSquarePolygonMeasure) { double deleft = points.AsEnumerable().Select(x => x.X).Min(); double deright = points.AsEnumerable().Select(x => x.X).Max(); double detop = points.AsEnumerable().Select(x => x.Y).Min(); double debottom = points.AsEnumerable().Select(x => x.Y).Max(); DPIRect = new Rect(deleft, detop, deright - deleft, debottom - detop); } MeasureEventArgs measureEvent = new MeasureEventArgs(); if (points.Count < 2) { measureEvent.Angle = 0; } else { Vector standVector = points[points.Count - 1] - points[points.Count - 2]; Vector endvector = closePoint - checkPoint; measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(endvector, standVector)); if (defaultSettingParam.IsCreateSquarePolygonMeasure) { measureEvent.Angle = 90; } } List pon = new List(); if (!defaultSettingParam.IsCreateSquarePolygonMeasure) { points.Add(checkPoint); } foreach (Point drawPoint in points) { Point savePoint = new Point( (drawPoint.X - pageBound.Left) + cropPoint.X, (drawPoint.Y - pageBound.Top) + cropPoint.Y); pon.Add(DpiHelper.StandardPointToPDFPoint(new Point( (float)drawPoint.X / zoomFactor, (float)drawPoint.Y / zoomFactor ))); } double area = measureSetting.ComputePolygonArea(pon.ToList()); double ratio = measureSetting.GetMeasureAreaRatio(); double rate = measureSetting.RulerTranslate / measureSetting.RulerBase; double inch = area * ratio * ratio * rate * rate; measureEvent.RulerTranslateUnit = measureSetting.RulerTranslateUnit; measureEvent.RulerTranslate = measureSetting.RulerTranslate; measureEvent.RulerBase = measureSetting.RulerBase; measureEvent.RulerBaseUnit = measureSetting.RulerBaseUnit; measureEvent.Precision = measureSetting.Precision; measureEvent.Type = CPDFMeasureType.CPDF_AREA_MEASURE; measureEvent.Distance = totalText.Text; measureEvent.Area = string.Format("{0} sq {1}", measureSetting.GetPrecisionData(inch), measureSetting.RulerTranslateUnit); MeasureChanged?.Invoke(this, measureEvent); } } private void DrawLineMeasure(DrawingContext drawingContext) { CPDFLineAnnotation polyLine = (cPDFAnnotation as CPDFLineAnnotation); byte[] bytes = polyLine.LineColor; Color color = ParamConverter.ConverterByteForColor(bytes); color.A = polyLine.GetTransparency(); Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth()); SolidColorBrush TextBrush = Brushes.Red; if (polyLine.IsMeasured()) { CPDFDistanceMeasure measureInfo = polyLine.GetDistanceMeasure(); if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3) { byte[] fontColor = measureInfo.TextAttribute.FontColor; TextBrush = new SolidColorBrush(Color.FromRgb(fontColor[0], fontColor[1], fontColor[2])); } if (polyLine.Dash != null && polyLine.Dash.Length > 0) { DashStyle dash = new DashStyle(); foreach (var offset in polyLine.Dash) { dash.Dashes.Add(offset / polyLine.LineWidth); } DrawPen.DashStyle = dash; DrawPen.DashCap = PenLineCap.Flat; } } if (isProportionalScaling) { mouseEndPoint = CalcAnglePoint(mouseEndPoint, mouseStartPoint, pageBound); } Point checkPoint = mouseEndPoint; checkPoint.X = Math.Max(pageBound.Left, checkPoint.X); checkPoint.X = Math.Min(pageBound.Right, checkPoint.X); checkPoint.Y = Math.Max(pageBound.Top, checkPoint.Y); checkPoint.Y = Math.Min(pageBound.Bottom, checkPoint.Y); double inch = measureSetting.GetMeasureLength(mouseStartPoint, checkPoint, zoomFactor); ArrowHelper drawLine = new ArrowHelper(); drawLine.LineStart = mouseStartPoint; drawLine.LineEnd = checkPoint; drawLine.ArrowLength = (uint)Math.Max(DrawPen.Thickness * 3, 12 * zoomFactor * zoomFactor); drawLine.StartSharp = polyLine.HeadLineType; drawLine.EndSharp = polyLine.TailLineType; drawLine.BuildArrowBody(); drawingContext?.DrawGeometry(null, DrawPen, drawLine.Body); drawingContext.DrawGeometry(null, DrawPen, drawLine.BuildArrowBody()); FormattedText formattedText = new FormattedText( string.Format("{0} {1}", measureSetting.GetPrecisionData(inch), measureSetting.RulerTranslateUnit), CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, new Typeface("YaHei"), 16, TextBrush); Vector movevector = checkPoint - mouseStartPoint; if (movevector.Length > formattedText.Width + textPadding) { if (checkPoint.X >= mouseStartPoint.X) { Point linePoint = new Point(mouseStartPoint.X + movevector.Length, mouseStartPoint.Y); Point drawPoint = new Point( linePoint.X - formattedText.Width - textPadding, linePoint.Y - formattedText.Height); Vector anglevector = linePoint - mouseStartPoint; RotateTransform transform = new RotateTransform(); transform.CenterX = mouseStartPoint.X; transform.CenterY = mouseStartPoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); drawingContext?.DrawText(formattedText, drawPoint); drawingContext.Pop(); } else { Point linePoint = new Point(mouseStartPoint.X - movevector.Length, mouseStartPoint.Y); Point drawPoint = new Point( linePoint.X + textPadding, linePoint.Y - formattedText.Height); Vector anglevector = linePoint - mouseStartPoint; RotateTransform transform = new RotateTransform(); transform.CenterX = mouseStartPoint.X; transform.CenterY = mouseStartPoint.Y; double angle = Vector.AngleBetween(movevector, anglevector); transform.Angle = -angle; drawingContext?.PushTransform(transform); drawingContext?.DrawText(formattedText, drawPoint); drawingContext.Pop(); } } DPIRect = new Rect(mouseStartPoint, checkPoint); if (drawPoints.Count <= 1) { drawPoints.Add(checkPoint); } else { drawPoints[1] = checkPoint; } Vector standVector = new Vector(1, 0); MeasureEventArgs measureEvent = new MeasureEventArgs(); measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(movevector, standVector)); measureEvent.RulerTranslateUnit = measureSetting.RulerTranslateUnit; measureEvent.RulerTranslate = measureSetting.RulerTranslate; measureEvent.RulerBase = measureSetting.RulerBase; measureEvent.RulerBaseUnit = measureSetting.RulerBaseUnit; measureEvent.Precision = measureSetting.Precision; Vector moveVector = checkPoint - mouseStartPoint; measureEvent.MousePos = new Point( (int)Math.Abs(moveVector.X / zoomFactor / 96D * 72D), (int)Math.Abs(moveVector.Y / zoomFactor / 96D * 72D)); measureEvent.Type = CPDFMeasureType.CPDF_DISTANCE_MEASURE; measureEvent.Distance = formattedText.Text; MeasureChanged?.Invoke(this, measureEvent); } #endregion public void MultipleClick(Point downPoint) { drawPoints.Add(downPoint); } public Rect GetMaxRect() { return maxRect; } public void CreateTextBox() { try { if (cPDFAnnotation != null && cPDFAnnotation.Type == C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT) { CPDFFreeTextAnnotation annotFreeText = (cPDFAnnotation as CPDFFreeTextAnnotation); TextBox textui = new TextBox(); Border textBorder = new Border(); textBorder.Child = textui; textui.Width = 200; CTextAttribute textAttribute = annotFreeText.FreeTextDa; byte transparency = annotFreeText.GetTransparency(); textui.FontSize = DpiHelper.PDFNumToStandardNum(textAttribute.FontSize * zoomFactor); Color textColor = Color.FromArgb( transparency, textAttribute.FontColor[0], textAttribute.FontColor[1], textAttribute.FontColor[2]); Color borderColor = Colors.Transparent; Color backgroundColor = Colors.White; byte[] colorArray = new byte[3]; if (annotFreeText.Transparency > 0) { borderColor = Color.FromRgb(annotFreeText.LineColor[0], annotFreeText.LineColor[1], annotFreeText.LineColor[2]); } if (annotFreeText.HasBgColor) { backgroundColor = Color.FromRgb(annotFreeText.BgColor[0], annotFreeText.BgColor[1], annotFreeText.BgColor[2]); } Point MousePoint = new Point((mouseStartPoint.X - pageBound.X), (mouseStartPoint.Y - pageBound.Y)); textBorder.MaxWidth = (pageBound.Width - MousePoint.X - cropPoint.X); textBorder.MaxHeight = (pageBound.Height - MousePoint.Y - cropPoint.Y); textui.Foreground = new SolidColorBrush(textColor); textui.Background = new SolidColorBrush(backgroundColor); textui.MinHeight = 40; textui.MinWidth = 200; textBorder.Padding = new Thickness(0); textBorder.BorderBrush = new SolidColorBrush(borderColor); textBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(annotFreeText.GetBorderWidth() * zoomFactor)); textui.BorderThickness = new Thickness(0); textui.Text = annotFreeText.Content; string fontName = string.Empty; string fontFamily = string.Empty; CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName); textui.FontFamily = new FontFamily(fontFamily); textui.AcceptsReturn = true; textui.TextWrapping = TextWrapping.Wrap; textui.TextAlignment = TextAlignment.Left; switch (annotFreeText.Alignment) { case C_TEXT_ALIGNMENT.ALIGNMENT_LEFT: textui.TextAlignment = TextAlignment.Left; break; case C_TEXT_ALIGNMENT.ALIGNMENT_RIGHT: textui.TextAlignment = TextAlignment.Right; break; case C_TEXT_ALIGNMENT.ALIGNMENT_CENTER: textui.TextAlignment = TextAlignment.Center; break; default: break; } textBorder.SetValue(Canvas.LeftProperty, mouseStartPoint.X); textBorder.SetValue(Canvas.TopProperty, mouseStartPoint.Y); lastTextui = textui; lastTextBorder = textBorder; textui.Loaded += (object sender, RoutedEventArgs e) => { textui.Focus(); textui.CaretIndex = textui.Text.Length; textui.SetValue(PopupTextAttachDataProperty, cPDFAnnotation); UpdateAnnotHandler?.Invoke(this, false); }; textui.LostFocus += (object sender, RoutedEventArgs e) => { CPDFAnnotation currentAnnot = textui.GetValue(PopupTextAttachDataProperty) as CPDFAnnotation; AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFViewer.GetDocument(), currentAnnot); if (currentAnnot != null && currentAnnot.IsValid()) { CPDFFreeTextAnnotation updateFreeText = currentAnnot as CPDFFreeTextAnnotation; if (textui.Text != string.Empty || updateFreeText.GetBorderWidth() != 0) { updateFreeText.SetContent(textui.Text); Rect changeRect = new Rect( DpiHelper.StandardNumToPDFNum(freeTextPoint.X), DpiHelper.StandardNumToPDFNum(freeTextPoint.Y), DpiHelper.StandardNumToPDFNum(textBorder.ActualWidth / zoomFactor), DpiHelper.StandardNumToPDFNum(textBorder.ActualHeight / zoomFactor)); updateFreeText.SetRect(new CRect( (float)changeRect.Left, (float)changeRect.Bottom, (float)changeRect.Right, (float)changeRect.Top )); updateFreeText.UpdateAp(); FreeTextAnnotHistory freeTextAnnotHistory = new FreeTextAnnotHistory(); annotParam = ParamConverter.AnnotConverter(cPDFViewer.GetDocument(), currentAnnot); annotParam.AnnotIndex = currentAnnot.Page.GetAnnotCount() - 1; freeTextAnnotHistory.CurrentParam = (FreeTextParam)annotParam; freeTextAnnotHistory.PDFDoc = cPDFViewer.GetDocument(); cPDFViewer.UndoManager.AddHistory(freeTextAnnotHistory); UpdateAnnotHandler?.Invoke(this, true); cPDFViewer.UndoManager?.InvokeHistoryChanged(this, new KeyValuePair(ComPDFKitViewer.Helper.UndoAction.Custom, freeTextAnnotHistory)); freeTextPoint = new Point(0, 0); } else { updateFreeText.RemoveAnnot(); CreateFreetextCanceled?.Invoke(this, annotParam); } } RemoveTextBox(); }; BaseLayer createAnnotTool = this; if (createAnnotTool != null) { createAnnotTool.Children.Add(textBorder); createAnnotTool.Arrange(); } textui.LayoutUpdated += (object sender, EventArgs e) => { createAnnotTool.Arrange(); }; } } catch { } } public void RemoveTextBox() { if (lastTextBorder == null) { return; } BaseLayer removeLayer = this; removeLayer.Children.Remove(lastTextBorder); } private void DrawText() { if (isProportionalScaling) { Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint); if (mouseOffset.X < 0) { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } } else { if (mouseOffset.Y > 0) { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X); } else { mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X); } } } Rect rect = new Rect(mouseStartPoint, mouseEndPoint); double mLeft = rect.Left; double mRight = rect.Right; double mUp = rect.Top; double mDown = rect.Bottom; if (rect.Left < maxRect.Left) { mLeft = maxRect.Left; } if (rect.Right > maxRect.Right) { mRight = maxRect.Right; } if (rect.Top < maxRect.Top) { mUp = maxRect.Top; } if (rect.Bottom > maxRect.Bottom) { mDown = maxRect.Bottom; } Rect drawRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp); DPIRect = drawRect; try { if (lastTextui != null && lastTextBorder != null && cPDFAnnotation != null && cPDFAnnotation.Type == C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT) { CPDFFreeTextAnnotation annotFreeText = (cPDFAnnotation as CPDFFreeTextAnnotation); CTextAttribute textAttribute = annotFreeText.FreeTextDa; byte transparency = annotFreeText.GetTransparency(); lastTextui.FontSize = DpiHelper.PDFNumToStandardNum(textAttribute.FontSize * zoomFactor); Color textColor = Color.FromArgb( transparency, textAttribute.FontColor[0], textAttribute.FontColor[1], textAttribute.FontColor[2]); Color borderColor = Colors.Transparent; Color backgroundColor = Colors.Transparent; byte[] colorArray = new byte[3]; if (annotFreeText.Transparency > 0) { borderColor = Color.FromArgb(annotFreeText.Transparency, annotFreeText.LineColor[0], annotFreeText.LineColor[1], annotFreeText.LineColor[2]); } if (annotFreeText.HasBgColor) { backgroundColor = Color.FromArgb(annotFreeText.Transparency, annotFreeText.BgColor[0], annotFreeText.BgColor[1], annotFreeText.BgColor[2]); } Border parentUI = lastTextui.Parent as Border; if (parentUI != null) { parentUI.SetValue(Canvas.LeftProperty, drawRect.Left); parentUI.SetValue(Canvas.TopProperty, drawRect.Top); // The width is incorrect if (mouseEndPoint.X >= mouseStartPoint.X) { parentUI.MaxWidth = (pageBound.Right - drawRect.X - cropPoint.X); } else { parentUI.MaxWidth = (drawRect.Right - pageBound.X - cropPoint.X); } if (mouseEndPoint.Y >= mouseStartPoint.Y) { parentUI.MaxHeight = (pageBound.Bottom - drawRect.Y - cropPoint.Y); } else { parentUI.MaxHeight = (drawRect.Bottom - pageBound.Y - cropPoint.Y); } } lastTextui.MinWidth = drawRect.Width; lastTextui.MinHeight = drawRect.Height; lastTextui.Foreground = new SolidColorBrush(textColor); lastTextui.Background = new SolidColorBrush(backgroundColor); lastTextBorder.Padding = new Thickness(0); lastTextBorder.BorderBrush = new SolidColorBrush(borderColor); lastTextBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(annotFreeText.GetBorderWidth() * zoomFactor)); lastTextui.BorderThickness = new Thickness(0); lastTextui.Text = annotFreeText.Content; lastTextui.Opacity = annotFreeText.Transparency; string fontName = string.Empty; string fontFamily = string.Empty; CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName); lastTextui.FontFamily = new FontFamily(fontFamily); lastTextui.FontWeight = IsBold(textAttribute.FontName) ? FontWeights.Bold : FontWeights.Normal; lastTextui.FontStyle = IsItalic(textAttribute.FontName) ? FontStyles.Italic : FontStyles.Normal; lastTextui.AcceptsReturn = true; lastTextui.TextWrapping = TextWrapping.Wrap; lastTextui.TextAlignment = TextAlignment.Left; switch (annotFreeText.Alignment) { case C_TEXT_ALIGNMENT.ALIGNMENT_LEFT: lastTextui.TextAlignment = TextAlignment.Left; break; case C_TEXT_ALIGNMENT.ALIGNMENT_RIGHT: lastTextui.TextAlignment = TextAlignment.Right; break; case C_TEXT_ALIGNMENT.ALIGNMENT_CENTER: lastTextui.TextAlignment = TextAlignment.Center; break; default: break; } } } catch { } } /// /// Use to calculate the point drawn at a fixed angle /// /// /// Current point /// /// /// Start point /// /// /// Maximum drawing area /// /// /// Return the calculated point /// internal Point CalcAnglePoint(Point currentPoint, Point startPoint, Rect pageBound) { Vector angleVector = currentPoint - startPoint; Point originPoint = new Point(startPoint.X, startPoint.Y - angleVector.Length); Vector orignVector = originPoint - startPoint; Rect checkRect = pageBound; int angle = (int)Vector.AngleBetween(orignVector, angleVector); if (angle < 0) { angle += 360; } int mod = angle % 45; int quot = angle / 45; Point anglePoint = currentPoint; int rotateAngle = 0; if (mod < 22) { Matrix rotateMatrix = new Matrix(); rotateAngle = quot * 45; rotateMatrix.RotateAt(rotateAngle, startPoint.X, startPoint.Y); anglePoint = rotateMatrix.Transform(originPoint); anglePoint = new Point((int)anglePoint.X, (int)anglePoint.Y); } else { Matrix rotateMatrix = new Matrix(); rotateAngle = (quot + 1) * 45; rotateMatrix.RotateAt(rotateAngle, startPoint.X, startPoint.Y); anglePoint = rotateMatrix.Transform(originPoint); anglePoint = new Point((int)anglePoint.X, (int)anglePoint.Y); } if (checkRect.Contains(anglePoint) == false) { switch (rotateAngle) { case 0: { anglePoint.X = startPoint.X; anglePoint.Y = Math.Max(checkRect.Top, Math.Min(anglePoint.Y, startPoint.Y)); } break; case 45: { double addValue = Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X); addValue = Math.Min(addValue, startPoint.Y - checkRect.Top); anglePoint.X = startPoint.X + addValue; anglePoint.Y = startPoint.Y - addValue; } break; case 90: { anglePoint.X = startPoint.X + Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X); anglePoint.Y = startPoint.Y; } break; case 135: { double addValue = Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X); addValue = Math.Min(addValue, checkRect.Bottom - startPoint.Y); anglePoint.X = startPoint.X + addValue; anglePoint.Y = startPoint.Y + addValue; } break; case 180: { anglePoint.X = startPoint.X; anglePoint.Y = Math.Min(anglePoint.Y, checkRect.Bottom); } break; case 225: { double addValue = Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left); addValue = Math.Min(addValue, checkRect.Bottom - startPoint.Y); anglePoint.X = startPoint.X - addValue; anglePoint.Y = startPoint.Y + addValue; } break; case 270: { anglePoint.X = startPoint.X - Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left); anglePoint.Y = startPoint.Y; } break; case 315: { double addValue = Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left); addValue = Math.Min(addValue, startPoint.Y - checkRect.Top); anglePoint.X = startPoint.X - addValue; anglePoint.Y = startPoint.Y - addValue; } break; case 360: { anglePoint.X = startPoint.X; anglePoint.Y = Math.Max(checkRect.Top, Math.Min(anglePoint.Y, startPoint.Y)); } break; default: break; } } return anglePoint; } } }