diff --git a/Annotations/TextPolygonSample/App.xaml b/Annotations/TextPolygonSample/App.xaml new file mode 100644 index 0000000..ca60a25 --- /dev/null +++ b/Annotations/TextPolygonSample/App.xaml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/Annotations/TextPolygonSample/App.xaml.cs b/Annotations/TextPolygonSample/App.xaml.cs new file mode 100644 index 0000000..429e7ba --- /dev/null +++ b/Annotations/TextPolygonSample/App.xaml.cs @@ -0,0 +1,16 @@ +namespace TextPolygonSample +{ + public partial class App : Application + { + public App() + { + Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Ix0oFS8QJAw9HSQvXkVhQlBad1RDX3xKf0x/TGpQb19xflBPallYVBYiSV9jS3tTfkdnWHdbd3dWRGZUWU91Xg=="); + InitializeComponent(); + } + + protected override Window CreateWindow(IActivationState? activationState) + { + return new Window(new AppShell()); + } + } +} \ No newline at end of file diff --git a/Annotations/TextPolygonSample/AppShell.xaml b/Annotations/TextPolygonSample/AppShell.xaml new file mode 100644 index 0000000..60cba9f --- /dev/null +++ b/Annotations/TextPolygonSample/AppShell.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/Annotations/TextPolygonSample/AppShell.xaml.cs b/Annotations/TextPolygonSample/AppShell.xaml.cs new file mode 100644 index 0000000..1ef84a0 --- /dev/null +++ b/Annotations/TextPolygonSample/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace TextPolygonSample +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} diff --git a/Annotations/TextPolygonSample/Assets/Annotations.pdf b/Annotations/TextPolygonSample/Assets/Annotations.pdf new file mode 100644 index 0000000..9192788 Binary files /dev/null and b/Annotations/TextPolygonSample/Assets/Annotations.pdf differ diff --git a/Annotations/TextPolygonSample/MainPage.xaml b/Annotations/TextPolygonSample/MainPage.xaml new file mode 100644 index 0000000..241a3a4 --- /dev/null +++ b/Annotations/TextPolygonSample/MainPage.xaml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Annotations/TextPolygonSample/MainPage.xaml.cs b/Annotations/TextPolygonSample/MainPage.xaml.cs new file mode 100644 index 0000000..cb4e340 --- /dev/null +++ b/Annotations/TextPolygonSample/MainPage.xaml.cs @@ -0,0 +1,128 @@ +using Syncfusion.Maui.PdfViewer; +using System.Globalization; + +namespace TextPolygonSample +{ + public partial class MainPage : ContentPage + { + // Define a variable to hold the polygon bounds and thickness for positioning other annotations + RectF polygonBounds; + float polygonThickness; + PolygonAnnotation? polygonAnnotation; + FreeTextAnnotation? textAnnotation; + + public MainPage() + { + InitializeComponent(); + + // Load a PDF document embedded in the project resources + Stream? documentStream = this.GetType().Assembly.GetManifestResourceStream("TextPolygonSample.Assets.Annotations.pdf"); + + // Load the PDF document into the SfPdfViewer + PdfViewer.LoadDocument(documentStream); + + // Call method to convert coordinates and add polygon annotations to the PDF + ConvertAndAddPolygonAnnotation(); + + // Create and add free text annotation within the polygon + CreateAndAddFreeTextAnnotation(); + } + + // Converts coordinate to polygon points and adds polygon and text annotations + void ConvertAndAddPolygonAnnotation() + { + // Example coordinates for a polygon + var coordinates = "M50 27L111 27L111 63L50 63"; + + // Create and add polygon annotation based on coordinate + CreateAndAddPolygonAnnotation(coordinates); + } + + // Creates and adds a free text annotation inside the polygon annotation + private void CreateAndAddFreeTextAnnotation() + { + // Text to be displayed within the free text annotation + string text = "TOMTEST"; + + // Calculate position and size of the free text annotation + float FreeTextX = polygonBounds.X + polygonThickness; + float FreeTextY = polygonBounds.Y + polygonThickness; + float FreeTextWidth = polygonBounds.Width - polygonThickness; + float FreeTextHeight = polygonBounds.Height - polygonThickness; + + // Define bounds for the free text annotation + RectF freeTextBounds = new RectF(FreeTextX, FreeTextY, FreeTextWidth, FreeTextHeight); + + // Create a free text annotation and add it to the PDF viewer + textAnnotation = new FreeTextAnnotation(text, 1, freeTextBounds); + PdfViewer.AddAnnotation(textAnnotation); + } + + // Converts coordinates to a list of points for the polygon annotation + public List ConvertCoordinatesToPolygonPoints(string coordinatesData) + { + // List to hold the parsed points + var points = new List(); + + // Split the coordinates data into commands based on the 'M' (move to) and 'L' (line to) commands + string[] commands = coordinatesData.Split(new char[] { 'M', 'L' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var command in commands) + { + // Separate each command into X and Y coordinates + string[] coords = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (coords.Length >= 2) + { + // Parse the coordinates and add to the list as a PointF object + float x = float.Parse(coords[0], CultureInfo.InvariantCulture); + float y = float.Parse(coords[1], CultureInfo.InvariantCulture); + points.Add(new PointF(x, y)); + } + } + return points; + } + + // Creates a polygon annotation from a list of points + private PolygonAnnotation CreatePolygonAnnotation(List polygonPoints) + { + // Create the polygon annotation and set its properties + PolygonAnnotation polygonAnnotation = new PolygonAnnotation(polygonPoints, 1); + polygonAnnotation.Color = Colors.Black; // Set annotation color + polygonAnnotation.Opacity = 25; // Set annotation opacity + + // Set the bounds and thickness for use in positioning other annotations + polygonBounds = polygonAnnotation.Bounds; + polygonThickness = polygonAnnotation.BorderWidth; + + // Set a solid border style for the polygon + polygonAnnotation.BorderStyle = BorderStyle.Solid; + + return polygonAnnotation; + } + + // Parses coordinate, creates a polygon annotation, and adds it to the PDF viewer + private void CreateAndAddPolygonAnnotation(string coordinate) + { + // Convert coordinate to a list of polygon points + List polygonPoints = ConvertCoordinatesToPolygonPoints(coordinate); + + // Create the polygon annotation from the points + polygonAnnotation = CreatePolygonAnnotation(polygonPoints); + + // Add the polygon annotation to the PDF document + PdfViewer.AddAnnotation(polygonAnnotation); + } + + //private void PdfViewer_AnnotationEdited(object sender, AnnotationEventArgs e) + //{ + // if (e.Annotation is FreeTextAnnotation annotation && annotation == textAnnotation && polygonAnnotation != null) + // { + // polygonBounds = annotation.Bounds; + // } + // if (polygonAnnotation != null) + // { + // polygonAnnotation.Bounds = polygonBounds; + // polygonAnnotation.Points = new List() { new PointF(polygonBounds.X, polygonBounds.Y), new PointF(polygonBounds.X + polygonBounds.Width, polygonBounds.Y), new PointF(polygonBounds.X, polygonBounds.Y + polygonBounds.Height), new PointF(polygonBounds.X + polygonBounds.Width, polygonBounds.Y + polygonBounds.Height) }; + // } + //} + } +} diff --git a/Annotations/TextPolygonSample/MauiProgram.cs b/Annotations/TextPolygonSample/MauiProgram.cs new file mode 100644 index 0000000..70124bb --- /dev/null +++ b/Annotations/TextPolygonSample/MauiProgram.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; +using Syncfusion.Maui.Core.Hosting; + +namespace TextPolygonSample +{ + public static class MauiProgram + { + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureSyncfusionCore() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + }); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } + } +} diff --git a/Annotations/TextPolygonSample/Platforms/Android/AndroidManifest.xml b/Annotations/TextPolygonSample/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..e9937ad --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Platforms/Android/MainActivity.cs b/Annotations/TextPolygonSample/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..ec11e0c --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Android/MainActivity.cs @@ -0,0 +1,11 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace TextPolygonSample +{ + [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] + public class MainActivity : MauiAppCompatActivity + { + } +} diff --git a/Annotations/TextPolygonSample/Platforms/Android/MainApplication.cs b/Annotations/TextPolygonSample/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..b240fd5 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Android/MainApplication.cs @@ -0,0 +1,16 @@ +using Android.App; +using Android.Runtime; + +namespace TextPolygonSample +{ + [Application] + public class MainApplication : MauiApplication + { + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/Annotations/TextPolygonSample/Platforms/Android/Resources/values/colors.xml b/Annotations/TextPolygonSample/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c04d749 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Platforms/MacCatalyst/AppDelegate.cs b/Annotations/TextPolygonSample/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..cdbb8ae --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace TextPolygonSample +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/Annotations/TextPolygonSample/Platforms/MacCatalyst/Entitlements.plist b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Entitlements.plist new file mode 100644 index 0000000..de4adc9 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Entitlements.plist @@ -0,0 +1,14 @@ + + + + + + + com.apple.security.app-sandbox + + + com.apple.security.network.client + + + + diff --git a/Annotations/TextPolygonSample/Platforms/MacCatalyst/Info.plist b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..7268977 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + UIDeviceFamily + + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/Annotations/TextPolygonSample/Platforms/MacCatalyst/Program.cs b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..0704fa9 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace TextPolygonSample +{ + public class Program + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } + } +} diff --git a/Annotations/TextPolygonSample/Platforms/Tizen/Main.cs b/Annotations/TextPolygonSample/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..ffc0f75 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Tizen/Main.cs @@ -0,0 +1,17 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Hosting; + +namespace TextPolygonSample +{ + internal class Program : MauiApplication + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } + } +} diff --git a/Annotations/TextPolygonSample/Platforms/Tizen/tizen-manifest.xml b/Annotations/TextPolygonSample/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..95ef2bd --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Platforms/Windows/App.xaml b/Annotations/TextPolygonSample/Platforms/Windows/App.xaml new file mode 100644 index 0000000..5df6443 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Windows/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/Annotations/TextPolygonSample/Platforms/Windows/App.xaml.cs b/Annotations/TextPolygonSample/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..ef44e3f --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Windows/App.xaml.cs @@ -0,0 +1,25 @@ +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace TextPolygonSample.WinUI +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : MauiWinUIApplication + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } + +} diff --git a/Annotations/TextPolygonSample/Platforms/Windows/Package.appxmanifest b/Annotations/TextPolygonSample/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..2c3e8c5 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,46 @@ + + + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Annotations/TextPolygonSample/Platforms/Windows/app.manifest b/Annotations/TextPolygonSample/Platforms/Windows/app.manifest new file mode 100644 index 0000000..deb3b5d --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/Windows/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Annotations/TextPolygonSample/Platforms/iOS/AppDelegate.cs b/Annotations/TextPolygonSample/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..cdbb8ae --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,10 @@ +using Foundation; + +namespace TextPolygonSample +{ + [Register("AppDelegate")] + public class AppDelegate : MauiUIApplicationDelegate + { + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + } +} diff --git a/Annotations/TextPolygonSample/Platforms/iOS/Info.plist b/Annotations/TextPolygonSample/Platforms/iOS/Info.plist new file mode 100644 index 0000000..0004a4f --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/iOS/Info.plist @@ -0,0 +1,32 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + + diff --git a/Annotations/TextPolygonSample/Platforms/iOS/Program.cs b/Annotations/TextPolygonSample/Platforms/iOS/Program.cs new file mode 100644 index 0000000..0704fa9 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/iOS/Program.cs @@ -0,0 +1,16 @@ +using ObjCRuntime; +using UIKit; + +namespace TextPolygonSample +{ + public class Program + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } + } +} diff --git a/Annotations/TextPolygonSample/Platforms/iOS/Resources/PrivacyInfo.xcprivacy b/Annotations/TextPolygonSample/Platforms/iOS/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..24ab3b4 --- /dev/null +++ b/Annotations/TextPolygonSample/Platforms/iOS/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,51 @@ + + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + E174.1 + + + + + + diff --git a/Annotations/TextPolygonSample/Properties/launchSettings.json b/Annotations/TextPolygonSample/Properties/launchSettings.json new file mode 100644 index 0000000..4f85793 --- /dev/null +++ b/Annotations/TextPolygonSample/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "Project", + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/Annotations/TextPolygonSample/README.md b/Annotations/TextPolygonSample/README.md new file mode 100644 index 0000000..28eb954 --- /dev/null +++ b/Annotations/TextPolygonSample/README.md @@ -0,0 +1,206 @@ +# How to add text inside a polygon annotation in .NET MAUI PDF Viewer? + +This project demonstrates how to add text inside a polygon annotation in [SfPdfViewer](https://help.syncfusion.com/cr/maui/Syncfusion.Maui.PdfViewer.SfPdfViewer.html). + +## Prerequisites + +1. A .NET MAUI project set up. +2. The [Syncfusion.Maui.PdfViewer](https://www.nuget.org/packages/Syncfusion.Maui.PdfViewer) package. + +## Steps + +### 1. Install Required NuGet Package + +Create a new [MAUI App](https://dotnet.microsoft.com/en-us/learn/maui/first-app-tutorial/create) and install the [Syncfusion.Maui.PdfViewer](https://www.nuget.org/packages/Syncfusion.Maui.PdfViewer) package using either. +* NuGet Package Manager +* NuGet CLI + +### 2. Initialize and Configure the PDF Viewer + +Start by adding the Syncfusion PDF Viewer control to your XAML file. + +**a. Add the Syncfusion namespace in `MainPage.xaml`** + +This namespace enables access to the PDF Viewer control. + +**XAML:** +```xaml + xmlns:syncfusion="clr-namespace:Syncfusion.Maui.PdfViewer;assembly=Syncfusion.Maui.PdfViewer" +``` + +**b. Add the PDF Viewer to your layout** + +**XAML:** +```xaml + + + +``` + +**c. Load the PDF in `MainPage.xaml.cs`** + +**C#:** +```csharp + public MainPage() + { + InitializeComponent(); + + // Load a PDF document embedded in the project resources + Stream? documentStream = this.GetType().Assembly.GetManifestResourceStream("TextPolygonSample.Assets.Annotations.pdf"); + + // Load the PDF document into the SfPdfViewer + PdfViewer.LoadDocument(documentStream); + } +``` + +### 3. Define a field to hold the polygon bounds and thickness for positioning FreeText annotations + +Declare fields in your `MainPage.xaml.cs` to store the bounds and thickness of the polygon annotation. These will be used to accurately position the free text annotation within the polygon. + +**C#:** +```csharp + RectF polygonBounds; + float polygonThickness; +``` + +### 4. Convert the Polygon annotation coordinates to list of points + +This method parses a string representation of polygon coordinates into a list of points. + +**C#:** +```csharp + public List ConvertCoordinatesToPolygonPoints(string coordinatesData) + { + // List to hold the parsed points + var points = new List(); + + // Split the coordinates data into commands based on the 'M' (move to) and 'L' (line to) commands + string[] commands = coordinatesData.Split(new char[] { 'M', 'L' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var command in commands) + { + // Separate each command into X and Y coordinates + string[] coords = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (coords.Length >= 2) + { + // Parse the coordinates and add to the list as a PointF object + float x = float.Parse(coords[0], CultureInfo.InvariantCulture); + float y = float.Parse(coords[1], CultureInfo.InvariantCulture); + points.Add(new PointF(x, y)); + } + } + return points; + } +``` + +### 5. Create a polygon annotation using the list of points + +This method constructs a `PolygonAnnotation` object from the provided points and configures its appearance and properties. + +**C#:** +```csharp + private PolygonAnnotation CreatePolygonAnnotation(List polygonPoints) + { + // Create the polygon annotation and set its properties + PolygonAnnotation polygonAnnotation = new PolygonAnnotation(polygonPoints, 1); + polygonAnnotation.Color = Colors.Black; // Set annotation color + polygonAnnotation.Opacity = 25; // Set annotation opacity + + // Set the bounds and thickness for use in positioning other annotations + polygonBounds = polygonAnnotation.Bounds; + polygonThickness = polygonAnnotation.BorderWidth; + + // Set a solid border style for the polygon + polygonAnnotation.BorderStyle = BorderStyle.Solid; + + return polygonAnnotation; + } +``` + +### 6. Parse the coordinate, create a polygon annotation, and adds it to the PDF viewer + +This method serves as a controller to parse the coordinate string, create the polygon annotation, and add it to the PDF viewer. + +**C#:** +```csharp + private void CreateAndAddPolygonAnnotation(string coordinate) + { + // Convert coordinate to a list of polygon points + List polygonPoints = ConvertCoordinatesToPolygonPoints(coordinate); + + // Create the polygon annotation from the points + PolygonAnnotation polygonAnnotation = CreatePolygonAnnotation(polygonPoints); + + // Add the polygon annotation to the PDF document + PdfViewer.AddAnnotation(polygonAnnotation); + } +``` + +### 7. Converts coordinate to polygon points and adds polygon annotations + +This method sets up the coordinates and triggers the creation and addition of the polygon annotation. + +**C#:** +```csharp + void ConvertAndAddPolygonAnnotation() + { + // Example coordinates for a polygon + var coordinates = "M50 27L111 27L111 63L50 63"; + + // Create and add polygon annotation based on coordinate + CreateAndAddPolygonAnnotation(coordinates); + } +``` + +### 8. Creates and adds a free text annotation inside the polygon annotation + +This method creates a text annotation and positions it within the defined polygon annotation's bounds. + +**C#:** +```csharp + private void CreateAndAddFreeTextAnnotation() + { + // Text to be displayed within the free text annotation + string text = "TOMTEST"; + + // Calculate position and size of the free text annotation + float FreeTextX = polygonBounds.X + polygonThickness; + float FreeTextY = polygonBounds.Y + polygonThickness; + float FreeTextWidth = polygonBounds.Width - polygonThickness; + float FreeTextHeight = polygonBounds.Height - polygonThickness; + + // Define bounds for the free text annotation + RectF freeTextBounds = new RectF(FreeTextX, FreeTextY, FreeTextWidth, FreeTextHeight); + + // Create a free text annotation and add it to the PDF viewer + FreeTextAnnotation textAnnotation = new FreeTextAnnotation(text, 1, freeTextBounds); + PdfViewer.AddAnnotation(textAnnotation); + } +``` + +### 9. Call the `ConvertAndAddPolygonAnnotation` and `CreateAndAddFreeTextAnnotation` in the `MainPage` constructor. + +The `MainPage` constructor initializes the page, loads the PDF document, and then calls the methods to add the polygon and free text annotations. + +**C#:** +```csharp + public MainPage() + { + InitializeComponent(); + + // Load a PDF document embedded in the project resources + Stream? documentStream = this.GetType().Assembly.GetManifestResourceStream("TextPolygonSample.Assets.Annotations.pdf"); + + // Load the PDF document into the SfPdfViewer + PdfViewer.LoadDocument(documentStream); + + // Call method to convert coordinates and add polygon annotations to the PDF + ConvertAndAddPolygonAnnotation(); + + // Create and add free text annotation within the polygon + CreateAndAddFreeTextAnnotation(); + } +``` + +## Run the App + +Build and run the application on you desired platform. \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Resources/AppIcon/appicon.svg b/Annotations/TextPolygonSample/Resources/AppIcon/appicon.svg new file mode 100644 index 0000000..9d63b65 --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/AppIcon/appicon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Resources/AppIcon/appiconfg.svg b/Annotations/TextPolygonSample/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Regular.ttf b/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..33b3e0d Binary files /dev/null and b/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Semibold.ttf b/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..a1f8571 Binary files /dev/null and b/Annotations/TextPolygonSample/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/Annotations/TextPolygonSample/Resources/Images/dotnet_bot.png b/Annotations/TextPolygonSample/Resources/Images/dotnet_bot.png new file mode 100644 index 0000000..1d1b981 Binary files /dev/null and b/Annotations/TextPolygonSample/Resources/Images/dotnet_bot.png differ diff --git a/Annotations/TextPolygonSample/Resources/Raw/AboutAssets.txt b/Annotations/TextPolygonSample/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..89dc758 --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/Raw/AboutAssets.txt @@ -0,0 +1,15 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories). Deployment of the asset to your application +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. + + + +These files will be deployed with your package and will be accessible using Essentials: + + async Task LoadMauiAsset() + { + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); + using var reader = new StreamReader(stream); + + var contents = reader.ReadToEnd(); + } diff --git a/Annotations/TextPolygonSample/Resources/Splash/splash.svg b/Annotations/TextPolygonSample/Resources/Splash/splash.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/Splash/splash.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Resources/Styles/Colors.xaml b/Annotations/TextPolygonSample/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..30307a5 --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/Styles/Colors.xaml @@ -0,0 +1,45 @@ + + + + + + + #512BD4 + #ac99ea + #242424 + #DFD8F7 + #9880e5 + #2B0B98 + + White + Black + #D600AA + #190649 + #1f1f1f + + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Annotations/TextPolygonSample/Resources/Styles/Styles.xaml b/Annotations/TextPolygonSample/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..86f574d --- /dev/null +++ b/Annotations/TextPolygonSample/Resources/Styles/Styles.xaml @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Annotations/TextPolygonSample/TextPolygonSample.csproj b/Annotations/TextPolygonSample/TextPolygonSample.csproj new file mode 100644 index 0000000..38c4a0b --- /dev/null +++ b/Annotations/TextPolygonSample/TextPolygonSample.csproj @@ -0,0 +1,76 @@ + + + + net9.0-android;net9.0-ios;net9.0-maccatalyst + $(TargetFrameworks);net9.0-windows10.0.19041.0 + + + + + + + Exe + TextPolygonSample + true + true + enable + enable + + + TextPolygonSample + + + com.companyname.textpolygonsample + + + 1.0 + 1 + + + None + + 15.0 + 15.0 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Annotations/TextPolygonSample/TextPolygonSample.sln b/Annotations/TextPolygonSample/TextPolygonSample.sln new file mode 100644 index 0000000..95b3596 --- /dev/null +++ b/Annotations/TextPolygonSample/TextPolygonSample.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36203.30 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TextPolygonSample", "TextPolygonSample.csproj", "{06054CB1-A829-4557-8076-96BB3818446A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {06054CB1-A829-4557-8076-96BB3818446A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06054CB1-A829-4557-8076-96BB3818446A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06054CB1-A829-4557-8076-96BB3818446A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06054CB1-A829-4557-8076-96BB3818446A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8C7F93CE-4D14-4C45-9AED-A134600A7CF8} + EndGlobalSection +EndGlobal