mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-11 17:59:17 +00:00
Fix #342: better async thumbnail loading
This commit is contained in:
Submodule QuickLook.Common updated: 44448c9f28...ef280ae2a5
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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<BitmapSource>(task, Loading);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuickLook.Plugin.PDFViewer
|
||||||
|
{
|
||||||
|
public sealed class NotifyTaskCompletion<TResult> : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly TResult _loading;
|
||||||
|
|
||||||
|
public NotifyTaskCompletion(Task<TResult> task, TResult loading = default(TResult))
|
||||||
|
{
|
||||||
|
Task = task;
|
||||||
|
_loading = loading;
|
||||||
|
if (!task.IsCompleted)
|
||||||
|
{
|
||||||
|
var _ = WatchTaskAsync(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<TResult> 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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -26,27 +26,45 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
{
|
{
|
||||||
internal static class PdfPageExtension
|
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];
|
lock (LockObj)
|
||||||
var factorX = 130d / size.Width;
|
{
|
||||||
var factorY = 210d / size.Height;
|
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);
|
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 scale = DpiHelper.GetCurrentScaleFactor();
|
||||||
var dpiX = fixDpi ? scale.Horizontal * DpiHelper.DefaultDpi : 96;
|
var dpiX = fixDpi ? scale.Horizontal * DpiHelper.DefaultDpi : 96;
|
||||||
var dpiY = fixDpi ? scale.Vertical * DpiHelper.DefaultDpi : 96;
|
var dpiY = fixDpi ? scale.Vertical * DpiHelper.DefaultDpi : 96;
|
||||||
|
|
||||||
|
Bitmap bitmap;
|
||||||
|
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
var size = doc.PdfDocument.PageSizes[page];
|
||||||
var realWidth = (int) Math.Round(size.Width * scale.Horizontal * factor);
|
var realWidth = (int) Math.Round(size.Width * scale.Horizontal * factor);
|
||||||
var realHeight = (int) Math.Round(size.Height * scale.Vertical * factor);
|
var realHeight = (int) Math.Round(size.Height * scale.Vertical * factor);
|
||||||
|
|
||||||
var bitmap = doc.Render(page, realWidth, realHeight, dpiX, dpiY,
|
bitmap = doc.PdfDocument.Render(page, realWidth, realHeight, dpiX, dpiY,
|
||||||
PdfRenderFlags.LimitImageCacheSize | PdfRenderFlags.LcdText | PdfRenderFlags.Annotations|PdfRenderFlags.ForPrinting) as Bitmap;
|
PdfRenderFlags.LimitImageCacheSize | PdfRenderFlags.LcdText | PdfRenderFlags.Annotations |
|
||||||
|
PdfRenderFlags.ForPrinting) as Bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
var bs = bitmap?.ToBitmapSource();
|
var bs = bitmap?.ToBitmapSource();
|
||||||
bitmap?.Dispose();
|
bitmap?.Dispose();
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
d:DesignWidth="720.29">
|
d:DesignWidth="720.29">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
<local:AsyncPageToThumbnailConverter x:Key="AsyncPageToThumbnailConverter" />
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="/QuickLook.Common;component/Styles/MainWindowStyles.xaml" />
|
<ResourceDictionary Source="/QuickLook.Common;component/Styles/MainWindowStyles.xaml" />
|
||||||
<ResourceDictionary Source="ListBoxItemStyleNoFocusedBorder.xaml" />
|
<ResourceDictionary Source="ListBoxItemStyleNoFocusedBorder.xaml" />
|
||||||
@@ -23,17 +24,20 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<ListBox x:Name="listThumbnails" Grid.Column="0" VirtualizingPanel.ScrollUnit="Pixel"
|
<ListBox x:Name="listThumbnails" Grid.Column="0" Width="150"
|
||||||
VirtualizingPanel.IsVirtualizing="True" Width="150"
|
|
||||||
SelectedIndex="0"
|
SelectedIndex="0"
|
||||||
Focusable="False"
|
Focusable="False"
|
||||||
|
HorizontalContentAlignment="Center"
|
||||||
|
VirtualizingStackPanel.IsVirtualizing="True"
|
||||||
|
VirtualizingStackPanel.VirtualizationMode="Recycling"
|
||||||
Background="Transparent" BorderThickness="0"
|
Background="Transparent" BorderThickness="0"
|
||||||
ItemsSource="{Binding PageThumbnails, ElementName=thisPdfViewer}"
|
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
ItemsSource="{Binding ElementName=thisPdfViewer, Path=PageThumbnails}"
|
||||||
ItemContainerStyle="{Binding Mode=OneWay, Source={StaticResource ListBoxItemStyleNoFocusedBorder}}">
|
ItemContainerStyle="{Binding Mode=OneWay, Source={StaticResource ListBoxItemStyleNoFocusedBorder}}">
|
||||||
<ListBox.ItemTemplate>
|
<ListBox.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid MaxHeight="150"
|
<Grid Height="150"
|
||||||
|
MinWidth="30"
|
||||||
MaxWidth="{Binding ViewportWidth, Mode=Default, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}}">
|
MaxWidth="{Binding ViewportWidth, Mode=Default, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="10" />
|
<ColumnDefinition Width="10" />
|
||||||
@@ -45,8 +49,15 @@
|
|||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="10" />
|
<RowDefinition Height="10" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Border x:Name="bbd" Grid.Row="1" Grid.Column="1" BorderThickness="1" BorderBrush="#33FFFFFF">
|
<Border x:Name="bbd" Grid.Row="1" Grid.Column="1" BorderThickness="1" BorderBrush="Gray">
|
||||||
<Image Source="{Binding}" />
|
<Image Source="{Binding Path=Result}">
|
||||||
|
<Image.DataContext>
|
||||||
|
<MultiBinding Converter="{StaticResource AsyncPageToThumbnailConverter}">
|
||||||
|
<Binding Path="PdfDocumentWrapper" ElementName="thisPdfViewer" />
|
||||||
|
<Binding />
|
||||||
|
</MultiBinding>
|
||||||
|
</Image.DataContext>
|
||||||
|
</Image>
|
||||||
</Border>
|
</Border>
|
||||||
<!--
|
<!--
|
||||||
<Label Grid.Row="1" Grid.Column="1" Content="{Binding Mode=OneWay, Converter={StaticResource MathConverter}, ConverterParameter=@VALUE+1}" FontSize="14" />
|
<Label Grid.Row="1" Grid.Column="1" Content="{Binding Mode=OneWay, Converter={StaticResource MathConverter}, ConverterParameter=@VALUE+1}" FontSize="14" />
|
||||||
|
@@ -22,10 +22,8 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using PdfiumViewer;
|
using PdfiumViewer;
|
||||||
using QuickLook.Common.ExtensionMethods;
|
using QuickLook.Common.ExtensionMethods;
|
||||||
|
|
||||||
@@ -41,9 +39,7 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
private double _maxZoomFactor = double.NaN;
|
private double _maxZoomFactor = double.NaN;
|
||||||
private double _minZoomFactor = double.NaN;
|
private double _minZoomFactor = double.NaN;
|
||||||
|
|
||||||
private PdfDocument _pdfHandle;
|
|
||||||
private bool _pdfLoaded;
|
private bool _pdfLoaded;
|
||||||
private Stream _pdfStream;
|
|
||||||
private double _viewRenderFactor = double.NaN;
|
private double _viewRenderFactor = double.NaN;
|
||||||
|
|
||||||
public PdfViewerControl()
|
public PdfViewerControl()
|
||||||
@@ -59,10 +55,9 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
pagePanel.ImageScrolled += NavigatePage;
|
pagePanel.ImageScrolled += NavigatePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<BitmapSource> PageThumbnails { get; set; } =
|
public ObservableCollection<int> PageThumbnails { get; set; } = new ObservableCollection<int>();
|
||||||
new ObservableCollection<BitmapSource>();
|
|
||||||
|
|
||||||
public int TotalPages => _pdfHandle.PageCount;
|
public int TotalPages => PdfDocumentWrapper.PdfDocument.PageCount;
|
||||||
|
|
||||||
public int CurrentPage
|
public int CurrentPage
|
||||||
{
|
{
|
||||||
@@ -77,6 +72,8 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PdfDocumentWrapper PdfDocumentWrapper { get; private set; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
@@ -88,9 +85,8 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
}
|
}
|
||||||
|
|
||||||
_pdfLoaded = false;
|
_pdfLoaded = false;
|
||||||
_pdfHandle?.Dispose();
|
PdfDocumentWrapper?.Dispose();
|
||||||
_pdfHandle = null;
|
PdfDocumentWrapper = null;
|
||||||
_pdfStream.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
@@ -154,7 +150,10 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
if (!_pdfLoaded)
|
if (!_pdfLoaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.WriteLine($"Renrendering page {CurrentPage}");
|
if (CurrentPage < 0 || CurrentPage >= TotalPages)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Debug.WriteLine($"Re-rendering page {CurrentPage}");
|
||||||
|
|
||||||
var pos = pagePanel.GetScrollPosition();
|
var pos = pagePanel.GetScrollPosition();
|
||||||
|
|
||||||
@@ -163,16 +162,16 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
// First time showing. Set thresholds here.
|
// First time showing. Set thresholds here.
|
||||||
if (double.IsNaN(_minZoomFactor) || double.IsNaN(_maxZoomFactor))
|
if (double.IsNaN(_minZoomFactor) || double.IsNaN(_maxZoomFactor))
|
||||||
{
|
{
|
||||||
factor = Math.Min(pagePanel.ActualHeight / _pdfHandle.PageSizes[CurrentPage].Height,
|
factor = Math.Min(pagePanel.ActualHeight / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Height,
|
||||||
pagePanel.ActualWidth / _pdfHandle.PageSizes[CurrentPage].Width);
|
pagePanel.ActualWidth / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Width);
|
||||||
_viewRenderFactor = factor;
|
_viewRenderFactor = factor;
|
||||||
_minZoomFactor = 0.1 * factor;
|
_minZoomFactor = 0.1 * factor;
|
||||||
_maxZoomFactor = 5 * factor;
|
_maxZoomFactor = 5 * factor;
|
||||||
}
|
}
|
||||||
else if (pagePanel.ZoomToFit)
|
else if (pagePanel.ZoomToFit)
|
||||||
{
|
{
|
||||||
factor = Math.Min(pagePanel.ActualHeight / _pdfHandle.PageSizes[CurrentPage].Height,
|
factor = Math.Min(pagePanel.ActualHeight / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Height,
|
||||||
pagePanel.ActualWidth / _pdfHandle.PageSizes[CurrentPage].Width);
|
pagePanel.ActualWidth / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -183,7 +182,7 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
pagePanel.MaxZoomFactor = _maxZoomFactor / factor;
|
pagePanel.MaxZoomFactor = _maxZoomFactor / factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
var image = _pdfHandle.Render(CurrentPage, factor);
|
var image = PdfDocumentWrapper.Render(CurrentPage, factor);
|
||||||
|
|
||||||
pagePanel.Source = image;
|
pagePanel.Source = image;
|
||||||
pagePanel.ResetZoom();
|
pagePanel.ResetZoom();
|
||||||
@@ -239,72 +238,31 @@ namespace QuickLook.Plugin.PDFViewer
|
|||||||
|
|
||||||
public void LoadPdf(string path)
|
public void LoadPdf(string path)
|
||||||
{
|
{
|
||||||
_pdfStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||||
_pdfHandle = PdfDocument.Load(_pdfStream);
|
PdfDocumentWrapper = new PdfDocumentWrapper(stream);
|
||||||
_pdfLoaded = true;
|
_pdfLoaded = true;
|
||||||
|
|
||||||
BeginLoadThumbnails(path);
|
BeginLoadThumbnails();
|
||||||
|
|
||||||
if (_pdfHandle.PageCount < 2)
|
if (PdfDocumentWrapper.PdfDocument.PageCount < 2)
|
||||||
listThumbnails.Visibility = Visibility.Collapsed;
|
listThumbnails.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadPdf(MemoryStream stream)
|
public void LoadPdf(MemoryStream stream)
|
||||||
{
|
{
|
||||||
_pdfStream = new MemoryStream();
|
stream.Position = 0;
|
||||||
stream.WriteTo(_pdfStream);
|
PdfDocumentWrapper = new PdfDocumentWrapper(stream);
|
||||||
_pdfStream.Position = 0;
|
|
||||||
|
|
||||||
_pdfHandle = PdfDocument.Load(_pdfStream);
|
|
||||||
_pdfLoaded = true;
|
_pdfLoaded = true;
|
||||||
|
|
||||||
BeginLoadThumbnails(stream);
|
BeginLoadThumbnails();
|
||||||
|
|
||||||
if (_pdfHandle.PageCount < 2)
|
if (PdfDocumentWrapper.PdfDocument.PageCount < 2)
|
||||||
listThumbnails.Visibility = Visibility.Collapsed;
|
listThumbnails.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginLoadThumbnails(string path, string password = null)
|
private void BeginLoadThumbnails()
|
||||||
{
|
{
|
||||||
new Task(() =>
|
Enumerable.Range(0, PdfDocumentWrapper.PdfDocument.PageCount).ForEach(PageThumbnails.Add);
|
||||||
{
|
|
||||||
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
||||||
{
|
|
||||||
using (var handle = PdfDocument.Load(stream, password))
|
|
||||||
{
|
|
||||||
for (var p = 0; p < handle.PageCount; p++)
|
|
||||||
{
|
|
||||||
var bs = handle.RenderThumbnail(p);
|
|
||||||
|
|
||||||
Dispatcher.BeginInvoke(new Action(() => PageThumbnails.Add(bs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
handle.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BeginLoadThumbnails(MemoryStream stream, string password = null)
|
|
||||||
{
|
|
||||||
var localStream = new MemoryStream();
|
|
||||||
stream.WriteTo(localStream);
|
|
||||||
localStream.Position = 0;
|
|
||||||
|
|
||||||
new Task(() =>
|
|
||||||
{
|
|
||||||
using (var handle = PdfDocument.Load(localStream, password))
|
|
||||||
{
|
|
||||||
for (var p = 0; p < handle.PageCount; p++)
|
|
||||||
{
|
|
||||||
var bs = handle.RenderThumbnail(p);
|
|
||||||
|
|
||||||
Dispatcher.BeginInvoke(new Action(() => PageThumbnails.Add(bs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
handle.Dispose();
|
|
||||||
}
|
|
||||||
}).Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
@@ -81,6 +81,9 @@
|
|||||||
<Compile Include="..\..\GitVersion.cs">
|
<Compile Include="..\..\GitVersion.cs">
|
||||||
<Link>Properties\GitVersion.cs</Link>
|
<Link>Properties\GitVersion.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="AsyncPageToThumbnailConverter.cs" />
|
||||||
|
<Compile Include="NotifyTaskCompletion.cs" />
|
||||||
|
<Compile Include="PdfDocumentWrapper.cs" />
|
||||||
<Compile Include="PdfViewerControl.xaml.cs">
|
<Compile Include="PdfViewerControl.xaml.cs">
|
||||||
<DependentUpon>PdfViewerControl.xaml</DependentUpon>
|
<DependentUpon>PdfViewerControl.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -113,6 +116,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Resources\loading.png" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@@ -1,4 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<packages>
|
<packages>
|
||||||
<package id="PdfiumViewer" version="2.13.0.0" targetFramework="net462" />
|
<package id="PdfiumViewer" version="2.13.0.0" targetFramework="net462" />
|
||||||
<package id="PdfiumViewer.Native.x86.v8-xfa" version="2018.4.8.256" targetFramework="net462" />
|
<package id="PdfiumViewer.Native.x86.v8-xfa" version="2018.4.8.256" targetFramework="net462" />
|
||||||
|
Reference in New Issue
Block a user