Пример #1
0
        public static async Task <InkingManager> InitializeInking(StorageFolder dataFolder, PdfModel pdfModel)
        {
            InkingManager inkManager = new InkingManager(dataFolder);

            inkManager.inAppInking = await InkingInApp.InitializeInking(dataFolder);

            inkManager.pdfModel = pdfModel;
            return(inkManager);
        }
Пример #2
0
 public static async Task<InkingManager> InitializeInking(StorageFolder dataFolder)
 {
     InkingManager inkManager = new InkingManager(dataFolder);
     inkManager.inAppInking = await InAppInking.InitializeInking(dataFolder);
     foreach (KeyValuePair<int, InkStrokeContainer> entry in inkManager.InkDictionary)
     {
         inkManager.inAppInkStrokes[entry.Key] = new List<InkStroke>(entry.Value.GetStrokes());
     }
     // TODO: Initialize in-file strokes
     return inkManager;
 }
Пример #3
0
 public async Task<bool> SaveInkingToPdf(InkingManager inkManager)
 {
     bool status = await sfPdf.SaveInkingToPdf(inkManager, msPdf.PdfDoc);
     return status;
 }
Пример #4
0
        /// <summary>
        /// Save the ink annotations into the pdf file.
        /// </summary>
        /// <param name="inkDictionary"></param>
        /// <returns></returns>
        /// <remarks>
        /// The page size returned from Syncfusion pdf is the media box size.
        /// The page size displayed to the end user is the crop box size.
        /// The size of the ink canvas is the same as the crop box size.
        /// Syncfusion uses the bottom left corner as the origin, while ink canvas uses the top left corner.
        /// </remarks>
        public async Task <bool> SaveInkingToPdf(InkingManager inkManager)
        {
            // Indicate whether any ink annotation is added to the PDF file
            bool fileChanged = false;

            // Remove ereased ink annotations
            foreach (KeyValuePair <int, List <InkStroke> > entry in await inkManager.ErasedStrokesDictionary())
            {
                // The key of the dictionary is page number, which is 1-based.
                int           pageNumber = entry.Key;
                PdfLoadedPage sfPage     = sfPdf.GetPage(pageNumber);
                // Get page information from MS model
                Windows.Data.Pdf.PdfPage msPage = msPdf.GetPage(pageNumber);

                PageMapping             mapping           = new PageMapping(msPage, sfPage);
                List <PdfInkAnnotation> erasedAnnotations = new List <PdfInkAnnotation>();
                // Add each ink stroke to the page
                foreach (InkStroke stroke in entry.Value)
                {
                    PdfInkAnnotation inkAnnotation = mapping.InkStroke2InkAnnotation(stroke);
                    erasedAnnotations.Add(inkAnnotation);
                }
                if (sfPdf.RemoveInkAnnotations(sfPage, erasedAnnotations))
                {
                    fileChanged = true;
                }
            }


            // Add new ink annotations
            foreach (KeyValuePair <int, InkStrokeContainer> entry in await inkManager.InAppInkDictionary())
            {
                PdfLoadedPage sfPage = sfPdf.GetPage(entry.Key);
                // Get page information from MS model
                Windows.Data.Pdf.PdfPage msPage = msPdf.GetPage(entry.Key);

                PageMapping mapping = new PageMapping(msPage, sfPage);

                // Add each ink stroke to the page
                foreach (InkStroke stroke in entry.Value.GetStrokes())
                {
                    PdfInkAnnotation inkAnnotation = mapping.InkStroke2InkAnnotation(stroke);
                    sfPage.Annotations.Add(inkAnnotation);
                    fileChanged = true;
                }
            }

            // Save the file only if there are changes.
            bool inkSaved = false;

            if (fileChanged)
            {
                try
                {
                    inkSaved = await sfPdf.SaveAsync();

                    // Copy and replace the actual file
                    await sfFile.CopyAndReplaceAsync(pdfFile);
                }
                catch (Exception ex)
                {
                    // Try to save the file by extracting the pages.
                    StorageFile newFile = await backupFolder.CreateFileAsync("COPY_" + pdfFile.Name, CreationCollisionOption.GenerateUniqueName);

                    try
                    {
                        await sfPdf.CopyPages(newFile);

                        inkSaved = true;
                        // Copy and replace the actual file
                        await newFile.CopyAndReplaceAsync(pdfFile);
                    }
                    catch
                    {
                        App.NotifyUser(typeof(ViewerPage), "Error: \n" + ex.Message, true);
                    }
                }
            }
            return(!(inkSaved ^ fileChanged));
        }
Пример #5
0
        /// <summary>
        /// Save the ink annotations into the pdf file.
        /// </summary>
        /// <param name="inkManager"></param>
        /// <returns></returns>
        /// <remarks>
        /// The page size returned from Syncfusion pdf is the media box size.
        /// The page size displayed to the end user is the crop box size.
        /// The size of the ink canvas is the same as the crop box size.
        /// Syncfusion uses the bottom left corner as the origin, while ink canvas uses the top left corner.
        /// </remarks>
        public async Task<bool> SaveInkingToPdf(InkingManager inkManager, Windows.Data.Pdf.PdfDocument pdfDoc)
        {
            // Indicate whether any ink annotation is added to the PDF file
            bool fileChanged = false;
            // Add ink annotations for each page
            foreach (KeyValuePair<int, InkStrokeContainer> entry in inkManager.InkDictionary)
            {
                // The key of the dictionary is page number, which is 1-based. Page index is 0-based.
                int pageIndex = entry.Key - 1;
                PdfLoadedPage sfPage = pdf.Pages[pageIndex] as PdfLoadedPage;
                // Get page information from MS model
                Windows.Data.Pdf.PdfPage msPage = pdfDoc.GetPage((uint)pageIndex);
                int rotation = (int)msPage.Rotation;
                // The page size returned from Syncfusion pdf is the media box size.
                double scaleRatio = sfPage.Size.Width / msPage.Dimensions.MediaBox.Width;

                // The ink canvas size is the same as crop box
                // Crop box could be smaller than media box
                // There will be an offset if the crop box is smaller than the media box.
                double xOffset = msPage.Dimensions.CropBox.Left * scaleRatio;
                double yOffset = msPage.Dimensions.CropBox.Top * scaleRatio;
                RectangleF rectangle = new RectangleF(0, 0, sfPage.Size.Width, sfPage.Size.Height);
                // Add each ink stroke to the page
                foreach (InkStroke stroke in entry.Value.GetStrokes())
                {
                    List<float> strokePoints = new List<float>();
                    foreach (InkPoint p in stroke.GetInkPoints())
                    {
                        float X = (float)(p.Position.X * scaleRatio + xOffset);
                        float Y = (float)(p.Position.Y * scaleRatio + yOffset);
                        switch (rotation)
                        {
                            case 0: // No rotation
                                {
                                    strokePoints.Add(X);
                                    strokePoints.Add(sfPage.Size.Height - Y);
                                    break;
                                }
                            case 1: // 90-degree rotation
                                {
                                    strokePoints.Add(Y);
                                    strokePoints.Add(X);
                                    break;
                                }
                            case 2: // 180-degree rotation
                                {
                                    strokePoints.Add(sfPage.Size.Width - X);
                                    strokePoints.Add(Y);
                                    break;
                                }
                            case 3: // 270-degree rotation
                                {
                                    strokePoints.Add(sfPage.Size.Height - Y);
                                    strokePoints.Add(sfPage.Size.Width - X);
                                    break;
                                }
                        }
                    }
                    PdfInkAnnotation inkAnnotation = new PdfInkAnnotation(rectangle, strokePoints);
                    // Color
                    inkAnnotation.Color = new PdfColor(fromUIColor(stroke.DrawingAttributes.Color));
                    // Size
                    inkAnnotation.BorderWidth = (int) Math.Round(stroke.DrawingAttributes.Size.Width * scaleRatio);
                    sfPage.Annotations.Add(inkAnnotation);
                    fileChanged = true;
                }
            }
            bool inkSaved = false;
            // Save the file only if there are changes.
            if (fileChanged)
            {
                try
                {
                    inkSaved = await pdf.SaveAsync(pdfFile);
                }
                catch (Exception ex)
                {
                    App.NotifyUser(typeof(ViewerPage), "Error: \n" + ex.Message, true);
                }
            }
            //pdf.Close(true);
            return !(inkSaved ^ fileChanged);
        }
Пример #6
0
        /// <summary>
        /// Converts an ink annotation (from the PDF file) to an ink stroke (to be displayed on the screen).
        /// </summary>
        /// <param name="inkAnnotation"></param>
        /// <param name="mapping"></param>
        /// <returns></returns>
        public InkStroke InkAnnotation2InkStroke(PdfLoadedInkAnnotation inkAnnotation)
        {
            List <float>     strokePoints = inkAnnotation.InkList;
            InkStrokeBuilder builder      = new InkStrokeBuilder();
            List <Point>     InkPoints    = new List <Point>();

            // Construct ink points
            for (int i = 0; i < strokePoints.Count; i = i + 2)
            {
                if ((i + 1) >= strokePoints.Count)
                {
                    // TODO: Something must be wrong.
                    break;
                }
                double X = 0, Y = 0;
                float  W = strokePoints[i];
                float  Z = strokePoints[i + 1];
                switch (Rotation)
                {
                case 0:     // No rotation
                {
                    X = W;
                    Y = PageSize.Height - Z;
                    break;
                }

                case 1:     // 90-degree rotation
                {
                    X = Z;
                    Y = W;
                    break;
                }

                case 2:     // 180-degree rotation
                {
                    X = PageSize.Width - W;
                    Y = Z;
                    break;
                }

                case 3:     // 270-degree rotation
                {
                    X = PageSize.Width - Z;
                    Y = PageSize.Height - W;
                    break;
                }
                }
                double pointX = (X - Offset.X) / ScaleRatio;
                double pointY = (Y - Offset.Y) / ScaleRatio;
                InkPoints.Add(new Point(pointX, pointY));
            }
            InkStroke stroke = builder.CreateStroke(InkPoints);

            Windows.UI.Color color = ColorToUI(inkAnnotation.Color);
            double           width = inkAnnotation.BorderWidth;

            if (width < InkingPreference.MIN_PEN_SIZE)
            {
                width = InkingPreference.MIN_PEN_SIZE;
            }
            width = width / ScaleRatio;
            Size size = new Size(width, width);

            if (inkAnnotation.Opacity == InkingManager.HighlighterOpacity)
            {
                stroke.DrawingAttributes = InkingManager.HighlighterDrawingAttributes(color, size);
            }
            else
            {
                stroke.DrawingAttributes = InkingManager.PencilDrawingAttributes(color, size);
            }


            return(stroke);
        }
Пример #7
0
 /// <summary>
 /// This method is not reliable.
 /// This method should only be called either right after getting the future access token, 
 /// or at the end of FinishInitialization() after fileLoaded has been set to true,
 /// depending on the performance and the size of the future access list.
 /// </summary>
 /// <returns></returns>
 private async Task CheckFutureAccessList()
 {
     string oldToken = null;
     AccessListEntryView futureAccessEntries = StorageApplicationPermissions.FutureAccessList.Entries;
     // If no recent file
     if (futureAccessEntries.Count == 0)
         return;
     else
     {
         System.Diagnostics.Stopwatch fileCheckingWatch = new System.Diagnostics.Stopwatch();
         fileCheckingWatch.Start();
         for (int i = 0; i < futureAccessEntries.Count; i++)
         {
             AccessListEntry entry = futureAccessEntries[i];
             if (entry.Token == this.futureAccessToken) continue;
             StorageFile pdfFileInList = null;
             try
             {
                 pdfFileInList = await StorageApplicationPermissions.FutureAccessList.GetFileAsync(entry.Token);
             }
             catch 
             {
                 // remove the entry if there is an exception
                 StorageApplicationPermissions.FutureAccessList.Remove(entry.Token);
             }
             if (pdfFileInList == null) continue;
             if (this.pdfStorageFile.IsEqual(pdfFileInList))
             {
                 oldToken = entry.Token;
                 StorageApplicationPermissions.FutureAccessList.Remove(entry.Token);
                 break;
             }
         }
         fileCheckingWatch.Stop();
         AppEventSource.Log.Debug("ViewerPage: Went through future access list in " + fileCheckingWatch.Elapsed.TotalSeconds.ToString() + " seconds");
     }
     if (oldToken != null)
     {
         AppEventSource.Log.Info("ViewerPage: File matched existing token in access list. " + oldToken);
         try
         {
             StorageFolder oldDataFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync(oldToken);
             await oldDataFolder.RenameAsync(this.futureAccessToken, NameCollisionOption.ReplaceExisting);
             AppEventSource.Log.Info("ViewerPage: Folder " + oldToken + " renamed to " + this.futureAccessToken);
             if (this.fileLoaded)
             {
                 this.dataFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync(this.futureAccessToken);
                 this.inkManager = await InkingManager.InitializeInking(dataFolder);
                 RefreshViewer();
             }
         }
         catch (Exception e)
         {
             if (e is FileNotFoundException)
             {
                 AppEventSource.Log.Warn("ViewerPage: Folder " + oldToken + " not found. ");
             }
             else throw new Exception(e.Message);
         }
     }
 }
Пример #8
0
 private async void FinishInitialization()
 {
     this.fullScreenCover.Visibility = Visibility.Collapsed;
     this.imagePanel.UpdateLayout();
     // Load viewer state
     await LoadViewerState();
     RestoreViewerState();
     // Load inking
     inkManager = await InkingManager.InitializeInking(dataFolder);
     // Make sure about the visible page range
     this._visiblePageRange = FindVisibleRange();
     this.fileLoaded = true;
     this.fileLoadingWatch.Stop();
     RefreshViewer();
     AppEventSource.Log.Info("ViewerPage: Finished Preparing the file in " + fileLoadingWatch.Elapsed.TotalSeconds.ToString());
     this.zoomOutGrid.ItemsSource = pageThumbnails;
     this.recycleTimer.Start();
 }