Sfoglia il codice sorgente

ComPDFKit(win) - 多边形已有代码

liuaoran 4 settimane fa
parent
commit
4fcf1347ba

+ 7 - 2
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/PolygonParam.cs

@@ -10,15 +10,20 @@ namespace ComPDFKit.Tool
 {
     public class PolygonParam : AnnotParam
     {
-        public double LineWidth { get; set; }
+        public byte[] FillColor { get; set; }
+        public bool HasFillColor { get; set; }
+        public float LineWidth { get; set; }
         public byte[] LineColor { get; set; }
         public List<CPoint> SavePoints { get; set; }
         public C_BORDER_INTENSITY Intensity { set; get; }
         public C_BORDER_STYLE Style { set; get; }
+        public float[] LineDash { get; set; }
+        public bool IsMeasure = false;
         public PolygonParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON;
-        }
+            
 
+        }  
     }
 }

+ 7 - 2
Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs

@@ -494,7 +494,10 @@ namespace ComPDFKit.Tool.SettingParam
         {
             soundParamDef = new SoundParam();
         }
-
+        private void InitPolygon()
+        {
+            polygonParamDef = new PolygonParam();
+        }
         #endregion
 
         #region Widget
@@ -741,7 +744,7 @@ namespace ComPDFKit.Tool.SettingParam
             InitCircle();
             InitStickyNote();
             InitSound();
-
+            InitPolygon();
             #endregion
 
             #region Widget
@@ -764,6 +767,8 @@ namespace ComPDFKit.Tool.SettingParam
             #endregion
         }
 
+
+
         public bool SetAnnotParam(AnnotParam annotParam)
         {
             bool IsOK = false;

+ 242 - 0
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonAnnotHistory.cs

@@ -0,0 +1,242 @@
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFPage;
+using ComPDFKit.Tool.Help;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ComPDFKit.Tool.UndoManger
+{
+    public class PolygonAnnotHistory : AnnotHistory
+    {
+        public override int GetAnnotIndex()
+        {
+            if (CurrentParam != null)
+            {
+                return CurrentParam.AnnotIndex;
+            }
+            return base.GetAnnotIndex();
+        }
+
+        public override int GetPageIndex()
+        {
+            if (CurrentParam != null)
+            {
+                return CurrentParam.PageIndex;
+            }
+            return base.GetPageIndex();
+        }
+
+        public override void SetAnnotIndex(int newIndex)
+        {
+            if (CurrentParam != null)
+            {
+                CurrentParam.AnnotIndex = newIndex;
+            }
+
+            if (PreviousParam != null)
+            {
+                PreviousParam.AnnotIndex = newIndex;
+            }
+        }
+
+        internal override bool Add()
+        {
+            PolygonParam currentParam = CurrentParam as PolygonParam;
+            if (CurrentParam == null || PDFDoc == null || !PDFDoc.IsValid())
+            {
+                return false;
+            }
+
+            CPDFPage pdfPage = PDFDoc.PageAtIndex(currentParam.PageIndex);
+            CPDFPolygonAnnotation polygonAnnot = pdfPage?.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON) as CPDFPolygonAnnotation;
+
+            if (polygonAnnot != null)
+            {
+                int annotIndex = pdfPage.GetAnnotCount() - 1;
+
+                if (currentParam.HasFillColor)
+                {
+                    if (currentParam.FillColor != null && currentParam.FillColor.Length == 3)
+                    {
+                        polygonAnnot.SetBgColor(currentParam.FillColor);
+                    }
+                }
+                if (currentParam.LineColor != null && currentParam.LineColor.Length == 3)
+                {
+                    polygonAnnot.SetLineColor(currentParam.LineColor);
+                }
+
+                polygonAnnot.SetTransparency((byte)currentParam.Transparency);
+                polygonAnnot.SetLineWidth(currentParam.LineWidth);
+
+                polygonAnnot.SetPoints(currentParam.SavePoints);
+                polygonAnnot.SetRect(currentParam.ClientRect);
+
+                if (currentParam.LineDash != null)
+                {
+                    if (currentParam.LineDash.Length == 0)
+                    {
+                        polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+                    }
+                    else
+                    {
+                        List<float> floatArray = new List<float>();
+                        foreach (float num in currentParam.LineDash)
+                        {
+                            floatArray.Add(num);
+                        }
+                        polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, floatArray.ToArray());
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(currentParam.Author))
+                {
+                    polygonAnnot.SetAuthor(currentParam.Author);
+                }
+
+                if (!string.IsNullOrEmpty(currentParam.Content))
+                {
+                    polygonAnnot.SetContent(currentParam.Content);
+                }
+
+                polygonAnnot.SetIsLocked(currentParam.Locked);
+                polygonAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+                polygonAnnot.UpdateAp();
+                polygonAnnot.ReleaseAnnot();
+
+                if (currentParam != null)
+                {
+                    currentParam.AnnotIndex = annotIndex;
+                }
+
+                if (PreviousParam != null)
+                {
+                    PreviousParam.AnnotIndex = annotIndex;
+                }
+                return true;
+            }
+            return true;
+        }
+
+        internal override bool Update(bool isUndo)
+        {
+            if (CurrentParam as PolygonParam == null || PreviousParam as PolygonParam == null)
+            {
+                return false;
+            }
+
+            if (MakeAnnotValid(CurrentParam))
+            {
+                CPDFPolygonAnnotation polygonAnnot = Annot as CPDFPolygonAnnotation;
+                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
+                {
+                    return false;
+                }
+
+
+                PolygonMeasureParam updateParam = (isUndo ? PreviousParam : CurrentParam) as PolygonMeasureParam;
+                PolygonMeasureParam checkParam = (isUndo ? CurrentParam : PreviousParam) as PolygonMeasureParam;
+
+                if (!CheckArrayEqual(updateParam.LineColor, checkParam.LineColor))
+                {
+                    if (updateParam.LineColor != null && updateParam.LineColor.Length == 3)
+                    {
+                        polygonAnnot.SetLineColor(updateParam.LineColor);
+                    }
+                }
+
+                if (!CheckArrayEqual(updateParam.FillColor, checkParam.FillColor))
+                {
+                    if (updateParam.HasFillColor)
+                    {
+                        if (updateParam.FillColor != null && updateParam.FillColor.Length == 3)
+                        {
+                            polygonAnnot.SetBgColor(updateParam.FillColor);
+                        }
+                    }
+                    else
+                    {
+                        polygonAnnot.ClearBgColor();
+                    }
+
+                    if (updateParam.Transparency != checkParam.Transparency)
+                    {
+                        polygonAnnot.SetTransparency((byte)updateParam.Transparency);
+                    }
+
+                    if (updateParam.LineWidth != checkParam.LineWidth)
+                    {
+                        polygonAnnot.SetLineWidth((byte)updateParam.LineWidth);
+                    }
+
+                    if (!CheckArrayEqual(updateParam.LineDash, checkParam.LineDash))
+                    {
+                        if (updateParam.LineDash != null)
+                        {
+                            if (updateParam.LineDash.Length == 0)
+                            {
+                                polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+                            }
+                            else
+                            {
+                                List<float> floatArray = new List<float>();
+                                foreach (float num in updateParam.LineDash)
+                                {
+                                    floatArray.Add(num);
+                                }
+                                polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, floatArray.ToArray());
+                            }
+                        }
+                    }
+
+
+                    if (!updateParam.SavePoints.SequenceEqual(checkParam.SavePoints))
+                    {
+                        polygonAnnot.SetPoints(updateParam.SavePoints);
+                    }
+
+                    if (!updateParam.ClientRect.Equals(checkParam.ClientRect))
+                    {
+                        polygonAnnot.SetRect(updateParam.ClientRect);
+                    }
+
+
+                    if (updateParam.Author != checkParam.Author)
+                    {
+                        polygonAnnot.SetAuthor(updateParam.Author);
+                    }
+
+                    if (updateParam.Content != checkParam.Content)
+                    {
+                        polygonAnnot.SetContent(updateParam.Content);
+                    }
+
+
+                    if (updateParam.Locked != checkParam.Locked)
+                    {
+                        polygonAnnot.SetIsLocked(updateParam.Locked);
+                    }
+                }
+                polygonAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
+
+                polygonAnnot.UpdateAp();
+
+                return true;
+            }
+            return false;
+        }
+
+        internal override bool Remove()
+        {
+            if (MakeAnnotValid(CurrentParam))
+            {
+                Annot.RemoveAnnot();
+                return true;
+            }
+            return false;
+        }
+    }
+}

+ 3 - 0
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonMeasureAnnotHistory.cs

@@ -31,6 +31,7 @@ namespace ComPDFKit.Tool.UndoManger
             }
             return base.GetPageIndex();
         }
+
         public override void SetAnnotIndex(int newIndex)
         {
             if (CurrentParam != null)
@@ -43,6 +44,7 @@ namespace ComPDFKit.Tool.UndoManger
                 PreviousParam.AnnotIndex = newIndex;
             }
         }
+
         internal override bool Add()
         {
             PolygonMeasureParam currentParam = CurrentParam as PolygonMeasureParam;
@@ -137,6 +139,7 @@ namespace ComPDFKit.Tool.UndoManger
             }
             return false;
         }
+
         internal override bool Update(bool isUndo)
         {
             if (CurrentParam as PolygonMeasureParam == null || PreviousParam as PolygonMeasureParam == null)

+ 2 - 1
Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml

@@ -76,7 +76,8 @@
             <Grid x:Name="StampGrid" Visibility="Collapsed">
                 <Image Margin="10" x:Name="StampImage"></Image>
             </Grid>
-            
+
+            <Grid x:Name="GdPolygon" Visibility="Collapsed"></Grid> 
         </Grid>
     </Border>
 </UserControl>

+ 74 - 1
Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml.cs

@@ -176,10 +176,83 @@ namespace ComPDFKit.Controls.PDFControl
             string fontStyle = string.Empty;
 
             CPDFFont.GetFamilyStyleName(freeTextData.FontFamily, ref fontFamily, ref fontStyle);
-            FreeText.FontFamily = new FontFamily(fontFamily); 
+            FreeText.FontFamily = new FontFamily(fontFamily);
             FreeText.FontSize = freeTextData.FontSize / 1.2;
             FreeText.Foreground = new SolidColorBrush(freeTextData.BorderColor);
             FreeText.Opacity = freeTextData.Opacity;
         }
+
+        public void DrawPolygonPreview(CPDFAnnotationData polygonData)
+        {
+            CollapsedAll();
+            GdPolygon.Visibility = Visibility.Visible;
+            Point startPoint = new Point(20, 70);
+            Point endPoint = new Point(200, 70);
+
+            Path cloudPath = DrawCloudLine(
+               startPoint,             // 起始点
+               endPoint,           // 终点
+                5,                          // 半径
+                120,                          // 角度
+                Brushes.Blue,                // 颜色
+                2.0,                          // 线宽
+                false
+            );
+
+            GdPolygon.Children.Add(cloudPath);
+        }
+
+        private Path DrawCloudLine(Point startPoint, Point endPoint, double radius, double angle, Brush strokeColor, double strokeThickness, bool isUpward)
+        {
+            double lineLength = Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
+            double arcLength = 2 * Math.PI * radius * (angle / 360);
+            int arcCount = (int)Math.Ceiling(lineLength / arcLength);
+            Vector direction = new Vector(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);
+
+            direction.Normalize();
+            direction *= arcLength; 
+            Point currentPoint = startPoint;
+            
+            // 创建一个完整的PathGeometry
+            PathGeometry pathGeometry = new PathGeometry(); 
+            PathFigure pathFigure = new PathFigure
+            {
+                StartPoint = currentPoint,
+                IsClosed = false
+            };
+            
+            for (int i = 0; i < arcCount; i++)
+            {
+                // Calculate the end point of the arc
+                Point nextPoint = new Point(currentPoint.X + direction.X, currentPoint.Y + direction.Y);
+
+                ArcSegment arcSegment = new ArcSegment
+                {
+                    Point = nextPoint,
+                    Size = new Size(radius, radius),
+                    SweepDirection = isUpward ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, // 控制圆弧方向
+                    IsLargeArc = angle > 180
+                };
+
+                // Add the ArcSegment to the path
+                pathFigure.Segments.Add(arcSegment);
+
+                // Update currentPoint to be the end point of the arc
+                currentPoint = nextPoint;
+            }
+
+            // 将所有圆弧段添加到一个PathFigure中
+            pathGeometry.Figures.Add(pathFigure);
+
+            // 创建最终的Path对象
+            Path cloudPath = new Path
+            {
+                Stroke = strokeColor,
+                StrokeThickness = strokeThickness,
+                Data = pathGeometry
+            };
+
+            return cloudPath;
+        } 
     }
 }

+ 3 - 1
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs

@@ -172,9 +172,11 @@ namespace ComPDFKit.Controls.Data
 
     public class CPDFPolygonData : CPDFAnnotationData
     {
-        public Color LineColor = Color.FromRgb(255, 0, 0);
+        public Color BorderColor = Color.FromRgb(255, 0, 0);
+        public Color FillColor = Color.FromRgb(255, 255, 255); 
         public double Opacity = 1;
         public int Thickness = 1;
+        public bool IsMeasured = false; 
         public DashStyle DashStyle = DashStyles.Solid;   
     }
 

+ 59 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml

@@ -0,0 +1,59 @@
+<UserControl x:Class="ComPDFKit.Controls.PDFControlUI.CPDFCloudUI"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:cpdfcommon="clr-namespace:ComPDFKit.Controls.Common" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:ComPDFKit.Controls.PDFControlUI" 
+             xmlns:cpdftools="clr-namespace:ComPDFKit.Controls.PDFControl" 
+             mc:Ignorable="d" 
+             d:DesignHeight="800" d:DesignWidth="300"> 
+    <UserControl.Resources> 
+        <ResourceDictionary> 
+            <ResourceDictionary.MergedDictionaries> 
+                <ResourceDictionary Source="../../../Asset/Styles/ToggleButtonStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+            <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
+        </ResourceDictionary> 
+    </UserControl.Resources> 
+    <ScrollViewer VerticalScrollBarVisibility="Auto"> 
+        <Grid Background="#FAFCFF"> 
+            <StackPanel Orientation="Vertical"> 
+                <Border BorderThickness="1" BorderBrush="#1A000000"> 
+                    <Grid  Height="40" Background="White" >
+                        <TextBlock x:Name="TitleTextBlock" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Cloud}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontFamily="Microsoft YaHei"></TextBlock>
+                    </Grid>
+                </Border>
+                <StackPanel Orientation="Vertical" Height="130">
+                    <cpdftools:CPDFAnnotationPreviewerControl x:Name="CPDFAnnotationPreviewerControl" Height="100" Margin="16"></cpdftools:CPDFAnnotationPreviewerControl>
+                </StackPanel>
+                <StackPanel Name="CloudPanel" Orientation="Vertical">
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineColor}"></TextBlock>
+                        <cpdfcommon:ColorPickerControl x:Name="ctlBorderColorPicker" TransparentBtnProperty="Collapsed"></cpdfcommon:ColorPickerControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FillColor}"></TextBlock>
+                        <cpdfcommon:ColorPickerControl x:Name="ctlFillColorPicker" TransparentBtnProperty="Collapsed"></cpdfcommon:ColorPickerControl>
+                    </StackPanel>
+                    <StackPanel Height="100" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineStyle}"></TextBlock>
+                        <cpdfcommon:CPDFCloudStyleControl x:Name="CPDFLineStyleControl"></cpdfcommon:CPDFCloudStyleControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
+                        <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl"></cpdfcommon:CPDFOpacityControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineWidth}"></TextBlock>
+                        <cpdfcommon:CPDFThicknessControl x:Name="CPDFThicknessControl"></cpdfcommon:CPDFThicknessControl>
+                    </StackPanel>
+                    <StackPanel Height="200" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Note}"></TextBlock>
+                        <TextBox Height="150" x:Name="NoteTextBox" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+                    </StackPanel>
+                </StackPanel>
+            </StackPanel>
+        </Grid>
+    </ScrollViewer>
+</UserControl>

+ 83 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml.cs

@@ -0,0 +1,83 @@
+using ComPDFKit.Controls.Data;
+using ComPDFKit.Controls.PDFControl;
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFDocument;
+using ComPDFKit.Tool;
+using ComPDFKit.Tool.UndoManger;
+using System;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace ComPDFKit.Controls.PDFControlUI
+{
+    /// <summary>
+    /// Interaction logic for CPDFCloudUI.xaml
+    /// </summary>
+    public partial class CPDFCloudUI : UserControl
+    {
+        private AnnotParam annotParam;
+        private CPDFAnnotation annotCore;
+        private PDFViewControl viewControl;
+        public event EventHandler<CPDFAnnotationData> PropertyChanged;
+
+        private AnnotHistory GetHistory()
+        {
+            if(annotCore != null && annotCore.IsValid())
+            {
+                return new PolygonAnnotHistory();
+            }
+            return new AnnotHistory();
+        }
+
+        public CPDFCloudUI()
+        {
+            InitializeComponent();
+
+            ctlBorderColorPicker.ColorChanged -= CtlBorderColorPicker_ColorChanged;
+            ctlFillColorPicker.ColorChanged -= CtlFillColorPicker_ColorChanged;
+            CPDFOpacityControl.OpacityChanged -= CPDFOpacityControl_OpacityChanged;
+
+            ctlBorderColorPicker.ColorChanged += CtlBorderColorPicker_ColorChanged;
+            ctlFillColorPicker.ColorChanged += CtlFillColorPicker_ColorChanged;
+            CPDFOpacityControl.OpacityChanged += CPDFOpacityControl_OpacityChanged;
+        }
+
+        private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
+        {
+            throw new NotImplementedException();
+        }
+
+        private void CtlFillColorPicker_ColorChanged(object sender, EventArgs e)
+        {
+            throw new NotImplementedException();
+        }
+
+        private void CtlBorderColorPicker_ColorChanged(object sender, EventArgs e)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void SetPresentAnnotAttrib(PolygonParam polygonParam, CPDFPolygonAnnotation annotation, CPDFDocument document, PDFViewControl view)
+        {
+            annotParam = polygonParam;
+            annotCore = annotation;
+            viewControl = view;
+        }
+
+        public CPDFAnnotationData GetPolygonData()
+        {
+            CPDFPolygonData polygonData = new CPDFPolygonData
+            {
+                AnnotationType = CPDFAnnotationType.Polygon,
+                BorderColor = ((SolidColorBrush)ctlBorderColorPicker.Brush).Color,
+                FillColor = ((SolidColorBrush)ctlFillColorPicker.Brush).Color,
+                IsMeasured = false,
+                Thickness = CPDFThicknessControl.Thickness,
+                Opacity = CPDFOpacityControl.Opacity / 100,
+                Note = NoteTextBox.Text
+            };
+
+            return polygonData;
+        }
+    }
+}

+ 104 - 0
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml

@@ -0,0 +1,104 @@
+<UserControl x:Class="ComPDFKit.Controls.Common.CPDFCloudStyleControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:ComPDFKit.Controls.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="70" d:DesignWidth="260">
+    <UserControl.Resources>
+        <Style x:Key="LineRadioButton" TargetType="{x:Type RadioButton}">
+            <Setter Property="HorizontalAlignment" Value="Left"></Setter>
+            <Setter Property="VerticalAlignment" Value="Center"></Setter>
+            <Setter Property="Height" Value="20"></Setter>
+            <Setter Property="Width" Value="200"></Setter>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="{x:Type RadioButton}">
+                        <Grid>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="20"></ColumnDefinition>
+                                <ColumnDefinition></ColumnDefinition>
+                            </Grid.ColumnDefinitions>
+                            <Grid Grid.Column="0">
+                                <Border x:Name="BackgroundBorder" CornerRadius="20" BorderThickness="2" BorderBrush="#000000" Background="Transparent">
+                                    <Ellipse Name="CheckedEllipse" Height="10" Width="10" Fill="#000000" Visibility="Collapsed"></Ellipse>
+                                </Border>
+                            </Grid>
+                            <ContentPresenter Grid.Column="1"/>
+                        </Grid>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsMouseOver" Value="True">
+                                <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="#477EDE"></Setter>
+                            </Trigger>
+
+                            <Trigger Property="IsPressed" Value="True">
+                                <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="#477EDE"></Setter>
+                                <Setter TargetName="BackgroundBorder" Property="Background" Value="#87CEFA"></Setter>
+                            </Trigger>
+
+                            <Trigger Property="IsChecked" Value="True">
+                                <Setter TargetName="CheckedEllipse" Property="Visibility" Value="Visible"></Setter>
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </UserControl.Resources>
+    <StackPanel  Margin="16,0,0,0" VerticalAlignment="Center">
+        <RadioButton IsChecked="True" Style="{StaticResource LineRadioButton}">
+            <Canvas VerticalAlignment="Center">
+                <Path Stroke="Black" StrokeThickness="2">
+                    <Path.Data>
+                        <PathGeometry>
+                            <PathFigure StartPoint="20,0">
+                                <ArcSegment Point="6,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="34,0">
+                                <ArcSegment Point="20,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="48,0">
+                                <ArcSegment Point="34,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="62,0">
+                                <ArcSegment Point="48,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="76,0">
+                                <ArcSegment Point="62,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="90,0">
+                                <ArcSegment Point="76,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                        </PathGeometry>
+                    </Path.Data>
+                </Path>
+            </Canvas>
+        </RadioButton>
+        <RadioButton  Style="{StaticResource LineRadioButton}" Margin="0,12,0,0">
+            <Canvas VerticalAlignment="Center">
+                <Path Stroke="Black" StrokeThickness="2">
+                    <Path.Data> 
+                        <PathGeometry>
+                            <PathFigure StartPoint="20,0">
+                                <ArcSegment Point="10,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="30,0">
+                                <ArcSegment Point="20,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="40,0">
+                                <ArcSegment Point="30,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="50,0">
+                                <ArcSegment Point="40,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="60,0">
+                                <ArcSegment Point="50,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                        </PathGeometry>
+                    </Path.Data>
+                </Path>
+            </Canvas>
+        </RadioButton>
+    </StackPanel>
+</UserControl>

+ 29 - 0
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace ComPDFKit.Controls.Common
+{
+    /// <summary>
+    /// Interaction logic for CPDFCloudStyleControl.xaml
+    /// </summary>
+    public partial class CPDFCloudStyleControl : UserControl
+    {
+        public CPDFCloudStyleControl()
+        {
+            DataContext = this;
+            InitializeComponent();
+        } 
+    }
+}