forked from unoplatform/uno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(PdfDocument): Inport initial implementation from PR unoplatform#…
- Loading branch information
1 parent
1a9b3a1
commit 0d2f7c3
Showing
9 changed files
with
403 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#if __ANDROID__ | ||
using System; | ||
using System.Threading.Tasks; | ||
using Android.Graphics.Pdf; | ||
using Uno; | ||
|
||
namespace Windows.Data.Pdf | ||
{ | ||
public partial class PdfDocument : IDisposable | ||
{ | ||
private readonly PdfRenderer pdfRenderer; | ||
|
||
private PdfDocument(PdfRenderer pdfRenderer) | ||
{ | ||
this.pdfRenderer = pdfRenderer ?? throw new ArgumentNullException(nameof(pdfRenderer)); | ||
} | ||
|
||
[NotImplemented] | ||
public bool IsPasswordProtected => false; | ||
|
||
public uint PageCount => (uint)pdfRenderer.PageCount; | ||
|
||
public PdfPage GetPage(uint pageIndex) | ||
{ | ||
if (pageIndex >= pdfRenderer.PageCount) | ||
{ | ||
throw new ArgumentOutOfRangeException(nameof(pageIndex), $"In this document the page index cannot be {pageIndex}. Page count is {pdfRenderer.PageCount}"); | ||
} | ||
|
||
var pdfPage = pdfRenderer.OpenPage((int)pageIndex); | ||
return new PdfPage(pdfPage); | ||
} | ||
|
||
public static Foundation.IAsyncOperation<PdfDocument> LoadFromFileAsync(Storage.IStorageFile file) | ||
{ | ||
if (file is null) | ||
{ | ||
throw new ArgumentNullException(nameof(file)); | ||
} | ||
|
||
#pragma warning disable Uno0001 // Uno type or member is not implemented | ||
var localpath = file.Path; | ||
#pragma warning restore Uno0001 // Uno type or member is not implemented | ||
var javaFile = new Java.IO.File(localpath); | ||
var fileDescriptor = Android.OS.ParcelFileDescriptor.Open(javaFile, Android.OS.ParcelFileMode.ReadOnly); | ||
var pdfRenderer = new PdfRenderer(fileDescriptor); | ||
var pdfDocument = new PdfDocument(pdfRenderer); | ||
|
||
return Task.FromResult(pdfDocument).AsAsyncOperation(); | ||
} | ||
|
||
|
||
[NotImplemented] | ||
public static Foundation.IAsyncOperation<PdfDocument> LoadFromFileAsync(Storage.IStorageFile file, string password) | ||
{ | ||
// password protected PDF files are not supported by PdfRenderer in Android | ||
throw new NotImplementedException("The member IAsyncOperation<PdfDocument> PdfDocument.LoadFromFileAsync(IStorageFile file, string password) is not implemented in Uno."); | ||
} | ||
|
||
[NotImplemented] | ||
public static Foundation.IAsyncOperation<PdfDocument> LoadFromStreamAsync(Storage.Streams.IRandomAccessStream inputStream) | ||
{ | ||
throw new NotImplementedException("The member IAsyncOperation<PdfDocument> PdfDocument.LoadFromStreamAsync(IRandomAccessStream inputStream) is not implemented in Uno."); | ||
} | ||
|
||
|
||
[NotImplemented] | ||
public static Foundation.IAsyncOperation<PdfDocument> LoadFromStreamAsync(Storage.Streams.IRandomAccessStream inputStream, string password) | ||
{ | ||
// password protected PDF files are not supported by PdfRenderer in Android | ||
throw new NotImplementedException("The member IAsyncOperation<PdfDocument> PdfDocument.LoadFromStreamAsync(IRandomAccessStream inputStream, string password) is not implemented in Uno."); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
pdfRenderer.Dispose(); | ||
} | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#if __ANDROID__ | ||
using System; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using Android.Graphics; | ||
using Android.Graphics.Pdf; | ||
using Uno; | ||
using Windows.Foundation; | ||
using Windows.Storage.Streams; | ||
using Windows.UI; | ||
using Color = Windows.UI.Color; | ||
using Rect = Windows.Foundation.Rect; | ||
|
||
namespace Windows.Data.Pdf | ||
{ | ||
public partial class PdfPage : IDisposable | ||
{ | ||
private readonly PdfRenderer.Page pdfPage; | ||
|
||
internal PdfPage(PdfRenderer.Page pdfPage) | ||
{ | ||
this.pdfPage = pdfPage ?? throw new ArgumentNullException(nameof(pdfPage)); | ||
} | ||
|
||
public PdfPageDimensions Dimensions { get; } = new PdfPageDimensions(); | ||
|
||
public uint Index => (uint)pdfPage.Index; | ||
|
||
[NotImplemented] | ||
public float PreferredZoom | ||
{ | ||
get | ||
{ | ||
throw new NotImplementedException("The member float PdfPage.PreferredZoom is not implemented in Uno."); | ||
} | ||
} | ||
|
||
[NotImplemented] | ||
public PdfPageRotation Rotation | ||
{ | ||
get | ||
{ | ||
throw new NotImplementedException("The member PdfPageRotation PdfPage.Rotation is not implemented in Uno."); | ||
} | ||
} | ||
|
||
public Size Size => new Size(pdfPage.Width, pdfPage.Height); | ||
|
||
public IAsyncAction RenderToStreamAsync(IRandomAccessStream outputStream) | ||
{ | ||
if (outputStream is null) | ||
{ | ||
throw new ArgumentNullException(nameof(outputStream)); | ||
} | ||
|
||
var options = new PdfPageRenderOptions | ||
{ | ||
DestinationWidth = (uint)pdfPage.Width, | ||
DestinationHeight = (uint)pdfPage.Height | ||
}; | ||
return RenderToStreamAsync(outputStream, options); | ||
} | ||
|
||
public IAsyncAction RenderToStreamAsync(IRandomAccessStream outputStream, PdfPageRenderOptions options) | ||
{ | ||
#region Validate arguments | ||
if (outputStream is null) | ||
{ | ||
throw new ArgumentNullException(nameof(outputStream)); | ||
} | ||
if (options is null) | ||
{ | ||
throw new ArgumentNullException(nameof(options)); | ||
} | ||
if (options.DestinationWidth > int.MaxValue) | ||
{ | ||
throw new ArgumentOutOfRangeException(nameof(options), $"PdfPageRenderOptions.DestinationWidth = {options.DestinationWidth}. Must be less than or equal to int.MaxValue"); | ||
} | ||
if (options.DestinationHeight > int.MaxValue) | ||
{ | ||
throw new ArgumentOutOfRangeException(nameof(options), $"PdfPageRenderOptions.DestinationHeight = {options.DestinationHeight}. Must be less than or equal to int.MaxValue"); | ||
} | ||
#endregion | ||
|
||
return Task.Run(() => | ||
{ | ||
const int quality = 100; | ||
var bitmap = RenderInternal(options); | ||
bitmap.Compress(Bitmap.CompressFormat.Png, quality, outputStream.AsStream()); | ||
return bitmap; | ||
}).AsAsyncAction(); | ||
} | ||
|
||
private Bitmap RenderInternal(PdfPageRenderOptions options) | ||
{ | ||
var destination = new Size(options.DestinationWidth, options.DestinationHeight); | ||
|
||
#region handle 0-width and 0-height | ||
if (destination.Width == 0 && destination.Height == 0) | ||
{ | ||
// destination size not set - render with the page original size | ||
destination = Size; | ||
} | ||
else if (destination.Width == 0) | ||
{ | ||
// destination width not set - calculate it based on height proportion | ||
var scale = destination.Height / Size.Height; | ||
destination = new Size(Size.Width * scale, destination.Height); | ||
} | ||
else if (destination.Height == 0) | ||
{ | ||
// destination height not set - calculate it based on width proportion | ||
var scale = destination.Width / Size.Width; | ||
destination = new Size(destination.Width, Size.Height * scale); | ||
} | ||
#endregion | ||
|
||
#region scale according to DPI | ||
var dpi = Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi / 96.0f; | ||
destination = new Size(destination.Width * dpi, destination.Height * dpi); | ||
#endregion | ||
|
||
#region create bitmap | ||
var bitmap = Bitmap.CreateBitmap((int)destination.Width, (int)destination.Height, Bitmap.Config.Argb8888); | ||
var destinationRect = new Rect(new Foundation.Point(), destination); | ||
#endregion | ||
|
||
#region fill with background color | ||
using (var canvas = new Canvas(bitmap)) | ||
{ | ||
var color = options.BackgroundColor.Equals(default(Color)) ? Colors.White : options.BackgroundColor; | ||
canvas.DrawRect(destinationRect, new Paint() | ||
{ | ||
Color = color | ||
}); | ||
} | ||
#endregion | ||
|
||
#region render only a portion of the page, defined by PdfPageRenderOptions.SourceRect, if set | ||
var sourceRect = options.SourceRect; | ||
Matrix matrix = null; | ||
if (sourceRect.Width > 0 && sourceRect.Height > 0) | ||
{ | ||
matrix = new Matrix(); | ||
matrix.SetRectToRect(AsAndroidRectF(sourceRect), AsAndroidRectF(destinationRect), Matrix.ScaleToFit.Start); | ||
} | ||
#endregion | ||
|
||
// Render content | ||
pdfPage.Render(bitmap, null, matrix, PdfRenderMode.ForDisplay); | ||
return bitmap; | ||
} | ||
|
||
public IAsyncAction PreparePageAsync() | ||
{ | ||
return Task.CompletedTask.AsAsyncAction(); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
pdfPage.Close(); | ||
pdfPage.Dispose(); | ||
} | ||
|
||
private static RectF AsAndroidRectF(Rect rect) => new RectF( | ||
(float)rect.Left, | ||
(float)rect.Top, | ||
(float)rect.Right, | ||
(float)rect.Bottom); | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#if __ANDROID__ | ||
using Windows.Foundation; | ||
|
||
namespace Windows.Data.Pdf | ||
{ | ||
public partial class PdfPageDimensions | ||
{ | ||
public Rect ArtBox { get; } | ||
public Rect BleedBox { get; } | ||
public Rect CropBox { get; } | ||
public Rect MediaBox { get; } | ||
public Rect TrimBox { get; } | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#if __ANDROID__ | ||
using System; | ||
using Windows.Foundation; | ||
using Windows.UI; | ||
|
||
namespace Windows.Data.Pdf | ||
{ | ||
public partial class PdfPageRenderOptions | ||
{ | ||
public Rect SourceRect { get; set; } | ||
|
||
public bool IsIgnoringHighContrast { get; set; } | ||
|
||
public uint DestinationWidth { get; set; } | ||
|
||
public uint DestinationHeight { get; set; } | ||
|
||
public Guid BitmapEncoderId { get; set; } | ||
|
||
public Color BackgroundColor { get; set; } | ||
} | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.