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
|
||||
{
|
||||
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;
|
||||
|
||||
Bitmap 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);
|
||||
|
||||
var bitmap = doc.Render(page, realWidth, realHeight, dpiX, dpiY,
|
||||
PdfRenderFlags.LimitImageCacheSize | PdfRenderFlags.LcdText | PdfRenderFlags.Annotations|PdfRenderFlags.ForPrinting) as Bitmap;
|
||||
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();
|
||||
|
@@ -12,6 +12,7 @@
|
||||
d:DesignWidth="720.29">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<local:AsyncPageToThumbnailConverter x:Key="AsyncPageToThumbnailConverter" />
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/QuickLook.Common;component/Styles/MainWindowStyles.xaml" />
|
||||
<ResourceDictionary Source="ListBoxItemStyleNoFocusedBorder.xaml" />
|
||||
@@ -23,17 +24,20 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox x:Name="listThumbnails" Grid.Column="0" VirtualizingPanel.ScrollUnit="Pixel"
|
||||
VirtualizingPanel.IsVirtualizing="True" Width="150"
|
||||
<ListBox x:Name="listThumbnails" Grid.Column="0" Width="150"
|
||||
SelectedIndex="0"
|
||||
Focusable="False"
|
||||
HorizontalContentAlignment="Center"
|
||||
VirtualizingStackPanel.IsVirtualizing="True"
|
||||
VirtualizingStackPanel.VirtualizationMode="Recycling"
|
||||
Background="Transparent" BorderThickness="0"
|
||||
ItemsSource="{Binding PageThumbnails, ElementName=thisPdfViewer}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ItemsSource="{Binding ElementName=thisPdfViewer, Path=PageThumbnails}"
|
||||
ItemContainerStyle="{Binding Mode=OneWay, Source={StaticResource ListBoxItemStyleNoFocusedBorder}}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid MaxHeight="150"
|
||||
<Grid Height="150"
|
||||
MinWidth="30"
|
||||
MaxWidth="{Binding ViewportWidth, Mode=Default, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="10" />
|
||||
@@ -45,8 +49,15 @@
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="10" />
|
||||
</Grid.RowDefinitions>
|
||||
<Border x:Name="bbd" Grid.Row="1" Grid.Column="1" BorderThickness="1" BorderBrush="#33FFFFFF">
|
||||
<Image Source="{Binding}" />
|
||||
<Border x:Name="bbd" Grid.Row="1" Grid.Column="1" BorderThickness="1" BorderBrush="Gray">
|
||||
<Image Source="{Binding Path=Result}">
|
||||
<Image.DataContext>
|
||||
<MultiBinding Converter="{StaticResource AsyncPageToThumbnailConverter}">
|
||||
<Binding Path="PdfDocumentWrapper" ElementName="thisPdfViewer" />
|
||||
<Binding />
|
||||
</MultiBinding>
|
||||
</Image.DataContext>
|
||||
</Image>
|
||||
</Border>
|
||||
<!--
|
||||
<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.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media.Imaging;
|
||||
using PdfiumViewer;
|
||||
using QuickLook.Common.ExtensionMethods;
|
||||
|
||||
@@ -41,9 +39,7 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
private double _maxZoomFactor = double.NaN;
|
||||
private double _minZoomFactor = double.NaN;
|
||||
|
||||
private PdfDocument _pdfHandle;
|
||||
private bool _pdfLoaded;
|
||||
private Stream _pdfStream;
|
||||
private double _viewRenderFactor = double.NaN;
|
||||
|
||||
public PdfViewerControl()
|
||||
@@ -59,10 +55,9 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
pagePanel.ImageScrolled += NavigatePage;
|
||||
}
|
||||
|
||||
public ObservableCollection<BitmapSource> PageThumbnails { get; set; } =
|
||||
new ObservableCollection<BitmapSource>();
|
||||
public ObservableCollection<int> PageThumbnails { get; set; } = new ObservableCollection<int>();
|
||||
|
||||
public int TotalPages => _pdfHandle.PageCount;
|
||||
public int TotalPages => PdfDocumentWrapper.PdfDocument.PageCount;
|
||||
|
||||
public int CurrentPage
|
||||
{
|
||||
@@ -77,6 +72,8 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
}
|
||||
}
|
||||
|
||||
public PdfDocumentWrapper PdfDocumentWrapper { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
@@ -88,9 +85,8 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
}
|
||||
|
||||
_pdfLoaded = false;
|
||||
_pdfHandle?.Dispose();
|
||||
_pdfHandle = null;
|
||||
_pdfStream.Close();
|
||||
PdfDocumentWrapper?.Dispose();
|
||||
PdfDocumentWrapper = null;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
@@ -154,7 +150,10 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
if (!_pdfLoaded)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Renrendering page {CurrentPage}");
|
||||
if (CurrentPage < 0 || CurrentPage >= TotalPages)
|
||||
return;
|
||||
|
||||
Debug.WriteLine($"Re-rendering page {CurrentPage}");
|
||||
|
||||
var pos = pagePanel.GetScrollPosition();
|
||||
|
||||
@@ -163,16 +162,16 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
// First time showing. Set thresholds here.
|
||||
if (double.IsNaN(_minZoomFactor) || double.IsNaN(_maxZoomFactor))
|
||||
{
|
||||
factor = Math.Min(pagePanel.ActualHeight / _pdfHandle.PageSizes[CurrentPage].Height,
|
||||
pagePanel.ActualWidth / _pdfHandle.PageSizes[CurrentPage].Width);
|
||||
factor = Math.Min(pagePanel.ActualHeight / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Height,
|
||||
pagePanel.ActualWidth / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Width);
|
||||
_viewRenderFactor = factor;
|
||||
_minZoomFactor = 0.1 * factor;
|
||||
_maxZoomFactor = 5 * factor;
|
||||
}
|
||||
else if (pagePanel.ZoomToFit)
|
||||
{
|
||||
factor = Math.Min(pagePanel.ActualHeight / _pdfHandle.PageSizes[CurrentPage].Height,
|
||||
pagePanel.ActualWidth / _pdfHandle.PageSizes[CurrentPage].Width);
|
||||
factor = Math.Min(pagePanel.ActualHeight / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Height,
|
||||
pagePanel.ActualWidth / PdfDocumentWrapper.PdfDocument.PageSizes[CurrentPage].Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -183,7 +182,7 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
pagePanel.MaxZoomFactor = _maxZoomFactor / factor;
|
||||
}
|
||||
|
||||
var image = _pdfHandle.Render(CurrentPage, factor);
|
||||
var image = PdfDocumentWrapper.Render(CurrentPage, factor);
|
||||
|
||||
pagePanel.Source = image;
|
||||
pagePanel.ResetZoom();
|
||||
@@ -239,72 +238,31 @@ namespace QuickLook.Plugin.PDFViewer
|
||||
|
||||
public void LoadPdf(string path)
|
||||
{
|
||||
_pdfStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
_pdfHandle = PdfDocument.Load(_pdfStream);
|
||||
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
PdfDocumentWrapper = new PdfDocumentWrapper(stream);
|
||||
_pdfLoaded = true;
|
||||
|
||||
BeginLoadThumbnails(path);
|
||||
BeginLoadThumbnails();
|
||||
|
||||
if (_pdfHandle.PageCount < 2)
|
||||
if (PdfDocumentWrapper.PdfDocument.PageCount < 2)
|
||||
listThumbnails.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public void LoadPdf(MemoryStream stream)
|
||||
{
|
||||
_pdfStream = new MemoryStream();
|
||||
stream.WriteTo(_pdfStream);
|
||||
_pdfStream.Position = 0;
|
||||
|
||||
_pdfHandle = PdfDocument.Load(_pdfStream);
|
||||
stream.Position = 0;
|
||||
PdfDocumentWrapper = new PdfDocumentWrapper(stream);
|
||||
_pdfLoaded = true;
|
||||
|
||||
BeginLoadThumbnails(stream);
|
||||
BeginLoadThumbnails();
|
||||
|
||||
if (_pdfHandle.PageCount < 2)
|
||||
if (PdfDocumentWrapper.PdfDocument.PageCount < 2)
|
||||
listThumbnails.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void BeginLoadThumbnails(string path, string password = null)
|
||||
private void BeginLoadThumbnails()
|
||||
{
|
||||
new Task(() =>
|
||||
{
|
||||
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();
|
||||
Enumerable.Range(0, PdfDocumentWrapper.PdfDocument.PageCount).ForEach(PageThumbnails.Add);
|
||||
}
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
|
@@ -81,6 +81,9 @@
|
||||
<Compile Include="..\..\GitVersion.cs">
|
||||
<Link>Properties\GitVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AsyncPageToThumbnailConverter.cs" />
|
||||
<Compile Include="NotifyTaskCompletion.cs" />
|
||||
<Compile Include="PdfDocumentWrapper.cs" />
|
||||
<Compile Include="PdfViewerControl.xaml.cs">
|
||||
<DependentUpon>PdfViewerControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -113,6 +116,9 @@
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Resources\loading.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@@ -1,4 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<packages>
|
||||
<package id="PdfiumViewer" version="2.13.0.0" targetFramework="net462" />
|
||||
<package id="PdfiumViewer.Native.x86.v8-xfa" version="2018.4.8.256" targetFramework="net462" />
|
||||
|
Reference in New Issue
Block a user