diff --git a/QuickLook.Common b/QuickLook.Common
index 44448c9..ef280ae 160000
--- a/QuickLook.Common
+++ b/QuickLook.Common
@@ -1 +1 @@
-Subproject commit 44448c9f28dc826db4c15e3e1b0b352b743b0885
+Subproject commit ef280ae2a568a2d41023c3747e6e1d91e88ed6c6
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/AsyncPageToThumbnailConverter.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/AsyncPageToThumbnailConverter.cs
new file mode 100644
index 0000000..08552a4
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/AsyncPageToThumbnailConverter.cs
@@ -0,0 +1,62 @@
+// Copyright © 2018 Paddy Xu
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+using System.Globalization;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using System.Windows.Media.Imaging;
+
+namespace QuickLook.Plugin.PDFViewer
+{
+ internal class AsyncPageToThumbnailConverter : IMultiValueConverter
+ {
+ private static readonly BitmapImage Loading =
+ new BitmapImage(
+ new Uri("pack://application:,,,/QuickLook.Plugin.PdfViewer;component/Resources/loading.png"));
+
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (values.Length < 2)
+ throw new Exception("PageIdToImageConverter");
+
+ if (!(values[0] is PdfDocumentWrapper handle)) return null;
+
+ var pageId = (int) values[1];
+ if (pageId < 0) return null;
+
+ var task = Task.Run(() =>
+ {
+ try
+ {
+ return handle.RenderThumbnail(pageId);
+ }
+ catch (Exception)
+ {
+ return Loading;
+ }
+ });
+
+ return new NotifyTaskCompletion(task, Loading);
+ }
+
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/NotifyTaskCompletion.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/NotifyTaskCompletion.cs
new file mode 100644
index 0000000..e9e8d1f
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/NotifyTaskCompletion.cs
@@ -0,0 +1,89 @@
+// Copyright © 2018 Paddy Xu
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+using System.ComponentModel;
+using System.Threading.Tasks;
+
+namespace QuickLook.Plugin.PDFViewer
+{
+ public sealed class NotifyTaskCompletion : INotifyPropertyChanged
+ {
+ private readonly TResult _loading;
+
+ public NotifyTaskCompletion(Task task, TResult loading = default(TResult))
+ {
+ Task = task;
+ _loading = loading;
+ if (!task.IsCompleted)
+ {
+ var _ = WatchTaskAsync(task);
+ }
+ }
+
+ public Task Task { get; }
+ public TResult Result => Task.Status == TaskStatus.RanToCompletion ? Task.Result : _loading;
+ public TaskStatus Status => Task.Status;
+ public bool IsCompleted => Task.IsCompleted;
+ public bool IsNotCompleted => !Task.IsCompleted;
+ public bool IsSuccessfullyCompleted => Task.Status ==
+ TaskStatus.RanToCompletion;
+ public bool IsCanceled => Task.IsCanceled;
+ public bool IsFaulted => Task.IsFaulted;
+ public AggregateException Exception => Task.Exception;
+ public Exception InnerException => Exception?.InnerException;
+ public string ErrorMessage => InnerException?.Message;
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ private async Task WatchTaskAsync(Task task)
+ {
+ try
+ {
+ await task;
+ }
+ catch
+ {
+ // ignored
+ }
+
+ var propertyChanged = PropertyChanged;
+ if (propertyChanged == null)
+ return;
+ propertyChanged(this, new PropertyChangedEventArgs("Status"));
+ propertyChanged(this, new PropertyChangedEventArgs("IsCompleted"));
+ propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted"));
+ if (task.IsCanceled)
+ {
+ propertyChanged(this, new PropertyChangedEventArgs("IsCanceled"));
+ }
+ else if (task.IsFaulted)
+ {
+ propertyChanged(this, new PropertyChangedEventArgs("IsFaulted"));
+ propertyChanged(this, new PropertyChangedEventArgs("Exception"));
+ propertyChanged(this,
+ new PropertyChangedEventArgs("InnerException"));
+ propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage"));
+ }
+ else
+ {
+ propertyChanged(this,
+ new PropertyChangedEventArgs("IsSuccessfullyCompleted"));
+ propertyChanged(this, new PropertyChangedEventArgs("Result"));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs
new file mode 100644
index 0000000..ca8d446
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs
@@ -0,0 +1,58 @@
+// Copyright © 2018 Paddy Xu
+//
+// This file is part of QuickLook program.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+using System;
+using System.IO;
+using PdfiumViewer;
+
+namespace QuickLook.Plugin.PDFViewer
+{
+ public class PdfDocumentWrapper : IDisposable
+ {
+ public PdfDocumentWrapper(Stream stream)
+ {
+ PdfStream = new MemoryStream((int) stream.Length);
+ stream.CopyTo(PdfStream);
+
+ PdfDocument = PdfDocument.Load(PdfStream);
+ }
+
+ public PdfDocument PdfDocument { get; private set; }
+
+ public MemoryStream PdfStream { get; private set; }
+
+ public void Dispose()
+ {
+ PdfDocument.Dispose();
+ PdfDocument = null;
+ PdfStream.Dispose();
+ PdfStream = null;
+ }
+
+ public void Refresh()
+ {
+ var oldD = PdfDocument;
+
+ PdfStream.Position = 0;
+ var newObj = new PdfDocumentWrapper(PdfStream);
+ PdfDocument = newObj.PdfDocument;
+ PdfStream = newObj.PdfStream;
+
+ oldD.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfPageExtension.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfPageExtension.cs
index e1b1d79..a65203d 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfPageExtension.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfPageExtension.cs
@@ -26,27 +26,45 @@ namespace QuickLook.Plugin.PDFViewer
{
internal static class PdfPageExtension
{
- public static BitmapSource RenderThumbnail(this PdfDocument doc, int page)
+ private static int _renderCount;
+ private static readonly object LockObj = new object();
+
+ public static BitmapSource RenderThumbnail(this PdfDocumentWrapper doc, int page)
{
- var size = doc.PageSizes[page];
- var factorX = 130d / size.Width;
- var factorY = 210d / size.Height;
+ lock (LockObj)
+ {
+ if (_renderCount++ == 50)
+ {
+ doc.Refresh();
+ _renderCount = 0;
+ }
+ }
+
+ var size = doc.PdfDocument.PageSizes[page];
+ var factorX = 60d / size.Width;
+ var factorY = 120d / size.Height;
return doc.Render(page, Math.Min(factorX, factorY), false);
}
- public static BitmapSource Render(this PdfDocument doc, int page, double factor, bool fixDpi = true)
+ public static BitmapSource Render(this PdfDocumentWrapper doc, int page, double factor, bool fixDpi = true)
{
- var size = doc.PageSizes[page];
var scale = DpiHelper.GetCurrentScaleFactor();
var dpiX = fixDpi ? scale.Horizontal * DpiHelper.DefaultDpi : 96;
var dpiY = fixDpi ? scale.Vertical * DpiHelper.DefaultDpi : 96;
- var realWidth = (int) Math.Round(size.Width * scale.Horizontal * factor);
- var realHeight = (int) Math.Round(size.Height * scale.Vertical * factor);
+ Bitmap bitmap;
- var bitmap = doc.Render(page, realWidth, realHeight, dpiX, dpiY,
- PdfRenderFlags.LimitImageCacheSize | PdfRenderFlags.LcdText | PdfRenderFlags.Annotations|PdfRenderFlags.ForPrinting) as Bitmap;
+ lock (LockObj)
+ {
+ var size = doc.PdfDocument.PageSizes[page];
+ var realWidth = (int) Math.Round(size.Width * scale.Horizontal * factor);
+ var realHeight = (int) Math.Round(size.Height * scale.Vertical * factor);
+
+ bitmap = doc.PdfDocument.Render(page, realWidth, realHeight, dpiX, dpiY,
+ PdfRenderFlags.LimitImageCacheSize | PdfRenderFlags.LcdText | PdfRenderFlags.Annotations |
+ PdfRenderFlags.ForPrinting) as Bitmap;
+ }
var bs = bitmap?.ToBitmapSource();
bitmap?.Dispose();
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml
index 4a5488c..f249174 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml
@@ -12,6 +12,7 @@
d:DesignWidth="720.29">
+
@@ -23,17 +24,20 @@
-
-
@@ -45,8 +49,15 @@
-
-
+
+
+
+
+
+
+
+
+