summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2014-04-24 22:58:57 -0700
committerMichael Vrhel <michael.vrhel@artifex.com>2014-09-09 16:39:34 -0700
commite3cd64f5b9db724368658b84f91027e7b53fe48a (patch)
tree26c5eec7e426b63ff9cbfce5f1c57446230dbb59 /platform
parent154922fa139a31768338eabcf87aa74871e85ece (diff)
downloadmupdf-e3cd64f5b9db724368658b84f91027e7b53fe48a.tar.xz
Addition of support to use mupdf clean to allow page extraction
Also support added to include mupdf devices in the output conversions.
Diffstat (limited to 'platform')
-rw-r--r--platform/winrt/gsview/Convert.xaml13
-rw-r--r--platform/winrt/gsview/Convert.xaml.cs31
-rw-r--r--platform/winrt/gsview/MainWindow.xaml53
-rw-r--r--platform/winrt/gsview/MainWindow.xaml.cs290
-rw-r--r--platform/winrt/gsview/PageExtractSave.xaml59
-rw-r--r--platform/winrt/gsview/PageExtractSave.xaml.cs214
-rw-r--r--platform/winrt/gsview/ghostsharp.cs11
-rw-r--r--platform/winrt/gsview/gsview.csproj7
-rw-r--r--platform/winrt/gsview/mudocument.cs240
-rw-r--r--platform/winrt/libmupdf_winRT.vcxproj2
-rw-r--r--platform/winrt/libmupdf_winRT.vcxproj.filters6
-rw-r--r--platform/winrt/mupdfnet/mupdfnet.cpp92
-rw-r--r--platform/winrt/mupdfnet/mupdfnet.h9
-rw-r--r--platform/winrt/mupdfwinrt/muctx.cpp101
-rw-r--r--platform/winrt/mupdfwinrt/muctx.h6
15 files changed, 1022 insertions, 112 deletions
diff --git a/platform/winrt/gsview/Convert.xaml b/platform/winrt/gsview/Convert.xaml
index eb8d4d72..73fcd488 100644
--- a/platform/winrt/gsview/Convert.xaml
+++ b/platform/winrt/gsview/Convert.xaml
@@ -1,7 +1,7 @@
<Window x:Class="gsview.Convert"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Ghostscript Convert" Height="215.96" Width="440.424">
+ Title="Convert Pages" Height="270.96" Width="419.424">
<DockPanel LastChildFill="True">
@@ -55,8 +55,10 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
</Grid.RowDefinitions>
-
+
<Grid Grid.Column="0" Grid.Row="0" Background="DarkGray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -103,9 +105,14 @@
<TextBlock Grid.Column="0" Grid.Row="1" Margin="5,10,0,0">
- <Bold>Options:</Bold>
+ <Bold>GhostScript Options:</Bold>
</TextBlock>
<TextBox x:Name="xaml_options" Grid.Row="2" Background="White" Height="40" Margin="5,5,5,5" Text=""></TextBox>
+ <TextBlock Grid.Column="0" Grid.Row="3" Margin="5,10,0,0">
+ <Bold>MuPDF Resolution:</Bold>
+ </TextBlock>
+ <TextBox x:Name="xaml_resolution" Grid.Row="4" Background="White" Margin="5,5,153,19" Text=""
+ PreviewTextInput="PreviewInput"/>
</Grid>
diff --git a/platform/winrt/gsview/Convert.xaml.cs b/platform/winrt/gsview/Convert.xaml.cs
index 6c33eb1a..9b2d5f66 100644
--- a/platform/winrt/gsview/Convert.xaml.cs
+++ b/platform/winrt/gsview/Convert.xaml.cs
@@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
+using System.Text.RegularExpressions;
namespace gsview
{
@@ -24,12 +25,24 @@ namespace gsview
internal set;
}
+ public gsDevice_t DeviceType
+ {
+ get;
+ internal set;
+ }
+
public bool SupportsMultiPage
{
get;
internal set;
}
+ public bool MuPDFDevice
+ {
+ get;
+ internal set;
+ }
+
public event PropertyChangedEventHandler PropertyChanged;
public void PageRefresh()
@@ -67,6 +80,7 @@ namespace gsview
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Page"));
+ PropertyChanged(this, new PropertyChangedEventArgs("PageString"));
}
}
};
@@ -100,10 +114,15 @@ namespace gsview
{
Device device_t = new Device();
device_t.DeviceName = Enum.GetName(typeof(gsDevice_t), device);
+ device_t.DeviceType = device;
if (device > gsDevice_t.psdrgb)
device_t.SupportsMultiPage = true;
else
device_t.SupportsMultiPage = false;
+ if (device < gsDevice_t.bmp16)
+ device_t.MuPDFDevice = true;
+ else
+ device_t.MuPDFDevice = false;
GSDevices.Add(device_t);
}
}
@@ -180,5 +199,17 @@ namespace gsview
(xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = false;
}
}
+
+ /* Allow only numbers */
+ private void PreviewInput(object sender, TextCompositionEventArgs e)
+ {
+ e.Handled = !IsTextAllowed(e.Text);
+ }
+
+ private static bool IsTextAllowed(string text)
+ {
+ Regex regex = new Regex("[^0-9]+");
+ return !regex.IsMatch(text);
+ }
}
}
diff --git a/platform/winrt/gsview/MainWindow.xaml b/platform/winrt/gsview/MainWindow.xaml
index cfd02b29..7307619e 100644
--- a/platform/winrt/gsview/MainWindow.xaml
+++ b/platform/winrt/gsview/MainWindow.xaml
@@ -1,7 +1,7 @@
<Window x:Class="gsview.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="gsview" Height="800" Width="650" UseLayoutRounding="True" >
+ Title="gsview" Height="850" Width="714" UseLayoutRounding="True" >
<!-- UseLayoutRouding needed to avoid funny interpolation effects on pages -->
<Window.Resources>
@@ -80,12 +80,6 @@
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
- <!-- <ItemsControl.ItemContainerStyle>
- <Style TargetType="ContentPresenter">
- <Setter Property="Canvas.Left" Value="{Binding Left}"/>
- <Setter Property="Canvas.Top" Value="{Binding Top}"/>
- </Style>
- </ItemsControl.ItemContainerStyle> -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Tag="{Binding Path=Index}" Width="{Binding Path=Width}" Height="{Binding Path=Height}" Fill="{Binding Path=Color}" IsEnabled="True" MouseDown="LinkClick">
@@ -139,6 +133,7 @@
<Image Source="Resources/saveHS.png" />
</MenuItem.Icon>
<MenuItem Header="PDF" Click="SavePDF" />
+ <MenuItem Header="Linearized PDF" Click="Linearize" x:Name="xaml_linearize_pdf"/>
<MenuItem Header="PDF-1.3" Click="SavePDF13" x:Name="xaml_savepdf13"/>
<MenuItem Header="PDF/A" x:Name="xaml_savepdfa">
<MenuItem Header="PDF/A-1 RGB" Click="SavePDFA1_RGB" x:Name="xaml_savepdfa1_rgb"/>
@@ -150,13 +145,9 @@
<MenuItem Header="PDF/X-3 CMYK" Click="SavePDFX3_CMYK" x:Name="xaml_savepdfx3_cmyk"/>
<MenuItem Header="PCL-XL" Click="SavePCLXL" x:Name="xaml_savepclxl"/>
<MenuItem Header="XPS" Click="SaveXPS"/>
- <MenuItem Header="SVG" Click="SaveSVG"/>
- <MenuItem Header="PCL/Bitmap" Click="SavePCL"/>
- <MenuItem Header="PNG" Click="SavePNG"/>
- <MenuItem Header="PWG" Click="SavePWG"/>
- <MenuItem Header="PNM" Click="SavePNM"/>
<MenuItem Header="TEXT" Click="SaveText"/>
<MenuItem Header="HTML" Click="SaveHTML"/>
+ <MenuItem Header="XML" Click="SaveXML"/>
</MenuItem>
<MenuItem Header="_Close" >
<MenuItem.Icon>
@@ -182,7 +173,7 @@
<MenuItem Header="SVG" Click="ExtractSVG" x:Name="xaml_extractsvg">
</MenuItem>
</MenuItem>
- <MenuItem Header="Ghostscript Convert..." Click="ConvertClick">
+ <MenuItem Header="Page Conversions..." Click="ConvertClick">
</MenuItem>
<Separator />
<MenuItem Header="Print..." Click="Print">
@@ -198,7 +189,11 @@
</MenuItem>
</MenuItem>
<MenuItem Header="_Edit" >
- <MenuItem Header="Extract PDF Pages" Click="ExtractPages"/>
+ <MenuItem Header="Extract PDF Pages" Click="ExtractPages" x:Name="xaml_Extract">
+ <MenuItem.Icon>
+ <Image Source="Resources/saveHS.png" />
+ </MenuItem.Icon>
+ </MenuItem>
<MenuItem Header="Copy Page" Click="CopyPage">
<MenuItem.Icon>
<Image Source="Resources/copy.ico" />
@@ -231,7 +226,6 @@
</MenuItem>
<MenuItem Header="Zoom Control" IsCheckable="true" Checked="ShowFooter" Unchecked="HideFooter"/>
</MenuItem>
-
<MenuItem Header="_Help" Click="OnHelpClick"/>
<MenuItem Header="About" Click="OnAboutClick"/>
@@ -575,7 +569,34 @@
</Button> -->
</Grid>
- <!-- The progress bar that runs during distilling -->
+ <!-- The progress bar that runs during MuPDF page by page conversion to file-->
+ <Grid x:Name="xaml_MuPDFGrid" DockPanel.Dock="Bottom" Visibility="Collapsed">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" />
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ <ProgressBar x:Name="xaml_MuPDFProgress" Grid.Row="0" Grid.Column="0" Margin="3" Minimum="0"
+ Maximum="100" Height="20" HorizontalAlignment="Stretch"/>
+ <TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="5, 0, 5, 0"><Bold>MuPDF Converting Document</Bold></TextBlock>
+ <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Name="xaml_CancelMuPDF" Click="CancelMuPDFClick" Background="Transparent" BorderBrush="Transparent" Margin="5,0,5,0">
+ <Button.Template>
+ <ControlTemplate TargetType="{x:Type Button}">
+ <Grid>
+ <Rectangle Height="Auto" RadiusX="5" RadiusY="5">
+ <Rectangle.Fill >
+ <SolidColorBrush Color="LightSlateGray"></SolidColorBrush>
+ </Rectangle.Fill>
+ </Rectangle>
+ <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
+ </Grid>
+ </ControlTemplate>
+ </Button.Template>
+ <TextBlock><Bold>Cancel</Bold></TextBlock>
+ </Button>
+ </Grid>
+
+ <!-- The progress bar that runs during GS distilling -->
<Grid x:Name="xaml_DistillGrid" DockPanel.Dock="Bottom" Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
diff --git a/platform/winrt/gsview/MainWindow.xaml.cs b/platform/winrt/gsview/MainWindow.xaml.cs
index d8dee6ef..9c0173fe 100644
--- a/platform/winrt/gsview/MainWindow.xaml.cs
+++ b/platform/winrt/gsview/MainWindow.xaml.cs
@@ -88,11 +88,10 @@ public enum Save_Type_t
PCLXL,
XPS,
SVG,
- PCLBitmap,
- PNG,
- PWG,
- PNM,
- TEXT
+ TEXT,
+ HTML,
+ XML,
+ LINEAR_PDF
}
public enum Extract_Type_t
@@ -212,7 +211,9 @@ namespace gsview
bool m_isXPS;
gsOutput m_gsoutput;
Convert m_convertwin;
+ PageExtractSave m_extractwin;
Password m_password = null;
+ String m_currpassword = null;
BackgroundWorker m_thumbworker = null;
BackgroundWorker m_textsearch = null;
BackgroundWorker m_linksearch = null;
@@ -253,6 +254,7 @@ namespace gsview
m_outputintents.Activate();
m_ghostscript.gsIOUpdateMain += new ghostsharp.gsIOCallBackMain(gsIO);
m_convertwin = null;
+ m_extractwin = null;
m_selection = null;
xaml_ZoomSlider.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(ZoomReleased), true);
@@ -349,6 +351,7 @@ namespace gsview
ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message);
}
status_t result = mu_doc.Initialize();
+ mu_doc.mupdfUpdateMain += new mudocument.mupdfCallBackMain(mupdfUpdate);
if (result != status_t.S_ISOK)
{
@@ -372,6 +375,7 @@ namespace gsview
m_doscroll = false;
m_intxtselect = false;
m_textselected = false;
+ m_currpassword = null;
return result;
}
@@ -495,7 +499,10 @@ namespace gsview
{
DisabletoPDF();
m_isXPS = true;
+ xaml_Extract.IsEnabled = false;
}
+ else
+ xaml_Extract.IsEnabled = true;
OpenFile2(dlg.FileName);
}
}
@@ -944,6 +951,41 @@ namespace gsview
m_gsoutput.Update(mess, len);
}
+ private void mupdfUpdate(object muObject, muPDFEventArgs asyncInformation)
+ {
+ if (asyncInformation.Completed)
+ {
+ xaml_MuPDFProgress.Value = 100;
+ xaml_MuPDFGrid.Visibility = System.Windows.Visibility.Collapsed;
+ if (asyncInformation.Params.result == GS_Result_t.gsFAILED)
+ {
+ ShowMessage(NotifyType_t.MESS_STATUS, "MuPDF failed to convert document");
+ }
+ MuPDFResult(asyncInformation.Params);
+ }
+ else
+ {
+ this.xaml_MuPDFProgress.Value = asyncInformation.Progress;
+ }
+ }
+
+ /* MuPDF Result*/
+ public void MuPDFResult(ConvertParams_t gs_result)
+ {
+ if (gs_result.result == GS_Result_t.gsCANCELLED)
+ {
+ xaml_MuPDFGrid.Visibility = System.Windows.Visibility.Collapsed;
+ return;
+ }
+ if (gs_result.result == GS_Result_t.gsFAILED)
+ {
+ xaml_MuPDFGrid.Visibility = System.Windows.Visibility.Collapsed;
+ ShowMessage(NotifyType_t.MESS_STATUS, "MuPDF Failed Conversion");
+ return;
+ }
+ ShowMessage(NotifyType_t.MESS_STATUS, "MuPDF Completed Conversion");
+ }
+
private void gsProgress(object gsObject, gsEventArgs asyncInformation)
{
if (asyncInformation.Completed)
@@ -1072,6 +1114,12 @@ namespace gsview
}
}
+ private void CancelMuPDFClick(object sender, RoutedEventArgs e)
+ {
+ xaml_CancelMuPDF.IsEnabled = false;
+ mu_doc.Cancel();
+ }
+
private void CancelDistillClick(object sender, RoutedEventArgs e)
{
xaml_CancelDistill.IsEnabled = false;
@@ -1108,13 +1156,20 @@ namespace gsview
private void ConvertReturn(object sender)
{
- if (m_ghostscript.GetStatus() != gsStatus.GS_READY)
+ Device device = (Device)m_convertwin.xaml_DeviceList.SelectedItem;
+ if (device == null)
+ {
+ ShowMessage(NotifyType_t.MESS_STATUS, "No Device Selected");
+ return;
+ }
+
+ if (m_ghostscript.GetStatus() != gsStatus.GS_READY &&
+ !device.MuPDFDevice)
{
ShowMessage(NotifyType_t.MESS_STATUS, "GS busy");
return;
}
- Device device = (Device)m_convertwin.xaml_DeviceList.SelectedItem;
System.Collections.IList pages = m_convertwin.xaml_PageList.SelectedItems;
System.Collections.IList pages_selected = null;
String options = m_convertwin.xaml_options.Text;
@@ -1129,64 +1184,146 @@ namespace gsview
return;
}
- if (device == null)
- {
- ShowMessage(NotifyType_t.MESS_STATUS, "No Device Selected");
- return;
- }
-
/* Get a filename */
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "All files (*.*)|*.*";
dlg.FilterIndex = 1;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
- if (!device.SupportsMultiPage && m_num_pages > 1)
- multi_page_needed = true;
-
- if (pages.Count != m_num_pages)
+ if (device.MuPDFDevice)
{
- /* We may need to go through page by page. Determine if
- * selection of pages is continuous. This is done by
- * looking at the first one in the list and the last one
- * in the list and checking the length */
- SelectPage lastpage = (SelectPage)pages[pages.Count - 1];
- SelectPage firstpage = (SelectPage)pages[0];
- int temp = lastpage.Page - firstpage.Page + 1;
- if (temp == pages.Count)
+ /* Allow only one of these as a time */
+ pages_selected = pages;
+ var val = m_convertwin.xaml_resolution.Text;
+ if (val.Length > 0)
{
- /* Pages are contiguous. Add first and last page
- * as command line option */
- options = options + " -dFirstPage=" + firstpage.Page + " -dLastPage=" + lastpage.Page;
- first_page = firstpage.Page;
- last_page = lastpage.Page;
+ bool isok = true;
+ int num = resolution;
+ try
+ {
+ num = System.Convert.ToInt32(val);
+ }
+ catch (FormatException e)
+ {
+ isok = false;
+ Console.WriteLine("Input string is not a sequence of digits.");
+ }
+ catch (OverflowException e)
+ {
+ isok = false;
+ Console.WriteLine("The number cannot fit in an Int32.");
+ }
+ if (isok && num > 0)
+ resolution = num;
}
- else
+
+ if (mu_doc.ConvertSave(device.DeviceType, dlg.FileName,
+ pages.Count, pages_selected, resolution) == gsStatus.GS_BUSY)
{
- /* Pages are not continguous. We will do this page
- * by page.*/
- pages_selected = pages;
- multi_page_needed = true; /* need to put in separate outputs */
+ ShowMessage(NotifyType_t.MESS_STATUS, "MuPDF conversion busy");
+ return;
}
+ xaml_CancelMuPDF.Visibility = System.Windows.Visibility.Visible;
+ xaml_MuPDFGrid.Visibility = System.Windows.Visibility.Visible;
}
- xaml_DistillProgress.Value = 0;
- if (m_ghostscript.Convert(m_currfile, options,
- device.DeviceName, dlg.FileName, pages.Count, resolution,
- multi_page_needed, pages_selected, first_page, last_page,
- null, null) == gsStatus.GS_BUSY)
+ else
{
- ShowMessage(NotifyType_t.MESS_STATUS, "GS busy");
- return;
+ if (!device.SupportsMultiPage && m_num_pages > 1)
+ multi_page_needed = true;
+
+ if (pages.Count != m_num_pages)
+ {
+ /* We may need to go through page by page. Determine if
+ * selection of pages is continuous. This is done by
+ * looking at the first one in the list and the last one
+ * in the list and checking the length */
+ SelectPage lastpage = (SelectPage)pages[pages.Count - 1];
+ SelectPage firstpage = (SelectPage)pages[0];
+ int temp = lastpage.Page - firstpage.Page + 1;
+ if (temp == pages.Count)
+ {
+ /* Pages are contiguous. Add first and last page
+ * as command line option */
+ options = options + " -dFirstPage=" + firstpage.Page + " -dLastPage=" + lastpage.Page;
+ first_page = firstpage.Page;
+ last_page = lastpage.Page;
+ }
+ else
+ {
+ /* Pages are not continguous. We will do this page
+ * by page.*/
+ pages_selected = pages;
+ multi_page_needed = true; /* need to put in separate outputs */
+ }
+ }
+ xaml_DistillProgress.Value = 0;
+ if (m_ghostscript.Convert(m_currfile, options,
+ device.DeviceName, dlg.FileName, pages.Count, resolution,
+ multi_page_needed, pages_selected, first_page, last_page,
+ null, null) == gsStatus.GS_BUSY)
+ {
+ ShowMessage(NotifyType_t.MESS_STATUS, "GS busy");
+ return;
+ }
+ xaml_DistillName.Text = "GS Converting Document";
+ xaml_CancelDistill.Visibility = System.Windows.Visibility.Collapsed;
+ xaml_DistillName.FontWeight = FontWeights.Bold;
+ xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible;
}
- xaml_DistillName.Text = "GS Converting Document";
- xaml_CancelDistill.Visibility = System.Windows.Visibility.Collapsed;
- xaml_DistillName.FontWeight = FontWeights.Bold;
- xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible;
m_convertwin.Close();
}
return;
}
+ private void ExtractPages(object sender, RoutedEventArgs e)
+ {
+ if (!m_init_done || m_isXPS)
+ return;
+
+ if (m_extractwin == null || !m_extractwin.IsActive)
+ {
+ m_extractwin = new PageExtractSave(m_num_pages);
+ m_extractwin.ExtractMain += new PageExtractSave.ExtractCallBackMain(ExtractReturn);
+ m_extractwin.Activate();
+ m_extractwin.Show();
+ }
+ }
+
+ private void ExtractReturn(object sender)
+ {
+ if (m_extractwin.xaml_PageList.SelectedItems.Count == 0)
+ {
+ ShowMessage(NotifyType_t.MESS_STATUS, "No Pages Selected");
+ return;
+ }
+
+ /* Go through the actual list not the selected items list. The
+ * selected items list contains them in the order that the were
+ * selected not the order graphically shown */
+ List<SelectPage> pages = new List<SelectPage>(m_extractwin.xaml_PageList.SelectedItems.Count);
+
+ for (int kk = 0; kk < m_extractwin.xaml_PageList.Items.Count; kk++)
+ {
+ var item = (m_extractwin.xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk)) as System.Windows.Controls.ListViewItem;
+ if (item.IsSelected == true)
+ {
+ pages.Add((SelectPage) m_extractwin.Pages[kk]);
+ }
+ }
+
+ /* Get a filename */
+ SaveFileDialog dlg = new SaveFileDialog();
+ dlg.Filter = "All files (*.pdf)|*.pdf";
+ dlg.FilterIndex = 1;
+ if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ {
+ mu_doc.PDFExtract(m_currfile, dlg.FileName, m_currpassword, m_currpassword != null,
+ false, pages.Count, pages);
+ m_extractwin.Close();
+ }
+ return;
+ }
+
private void GetPassword()
{
if (m_password == null)
@@ -1202,6 +1339,7 @@ namespace gsview
{
if (mu_doc.ApplyPassword(m_password.xaml_Password.Password))
{
+ m_currpassword = m_password.xaml_Password.Password;
m_password.Close();
m_password = null;
StartViewer();
@@ -1576,11 +1714,11 @@ namespace gsview
String options = null;
bool use_gs = true;
String init_file = CreatePDFXA(type);
- ;
+
switch (type)
{
case Save_Type_t.PDF:
- /* All done. No need to use gs */
+ /* All done. No need to use gs or mupdf */
System.IO.File.Copy(m_currfile, dlg.FileName, true);
use_gs = false;
break;
@@ -1632,13 +1770,13 @@ namespace gsview
bool use_mupdf = true;
switch (type)
{
- case Save_Type_t.PCLBitmap:
- break;
- case Save_Type_t.PNG:
- break;
- case Save_Type_t.PWG:
- break;
- case Save_Type_t.SVG:
+ case Save_Type_t.LINEAR_PDF:
+ dlg.Filter = "PDF (*.pdf)|*.pdf";
+ if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ {
+ mu_doc.PDFExtract(m_currfile, dlg.FileName, m_currpassword,
+ m_currpassword != null, true, -1, null);
+ }
break;
case Save_Type_t.PCLXL:
use_mupdf = false;
@@ -1672,31 +1810,11 @@ namespace gsview
}
}
- private void SavePNG(object sender, RoutedEventArgs e)
- {
- SaveFile(Save_Type_t.PNG);
- }
-
- private void SavePWG(object sender, RoutedEventArgs e)
- {
- SaveFile(Save_Type_t.PWG);
- }
-
- private void SavePNM(object sender, RoutedEventArgs e)
- {
- SaveFile(Save_Type_t.PNM);
- }
-
private void SaveSVG(object sender, RoutedEventArgs e)
{
SaveFile(Save_Type_t.SVG);
}
- private void SavePCL(object sender, RoutedEventArgs e)
- {
- SaveFile(Save_Type_t.PCLBitmap);
- }
-
private void SavePDF(object sender, RoutedEventArgs e)
{
SaveFile(Save_Type_t.PDF);
@@ -1709,7 +1827,12 @@ namespace gsview
private void SaveHTML(object sender, RoutedEventArgs e)
{
+ SaveFile(Save_Type_t.HTML);
+ }
+ private void Linearize(object sender, RoutedEventArgs e)
+ {
+ SaveFile(Save_Type_t.LINEAR_PDF);
}
private void SavePDF13(object sender, RoutedEventArgs e)
@@ -3022,9 +3145,9 @@ namespace gsview
{
var relPoint = e.GetPosition(xaml_PageList);
var absPoint = this.PointToScreen(relPoint);
- Console.Write("abs Y position = " + absPoint.Y + "\n");
+ /* Console.Write("abs Y position = " + absPoint.Y + "\n");
Console.Write("rel Y position = " + relPoint.Y + "\n");
- Console.Write("Height is = " + (this.Top + this.Height) + "\n");
+ Console.Write("Height is = " + (this.Top + this.Height) + "\n"); */
if (xaml_PageList.IsMouseCaptured == true)
{
@@ -3086,22 +3209,21 @@ namespace gsview
private void dispatcherTimerTick(object sender, EventArgs e)
{
var position = this.PointToScreen(Mouse.GetPosition(xaml_PageList));
- Console.Write("Y position = " + position.Y + "\n");
+ /* Console.Write("Y position = " + position.Y + "\n");
Console.Write("Top position = " + this.Top + "\n");
- Console.Write("Bottom position = " + (this.Top + this.Height) + "\n");
-
+ Console.Write("Bottom position = " + (this.Top + this.Height) + "\n"); */
DocPage page;
int page_num;
if (!xaml_PageList.IsMouseCaptured)
{
- Console.Write("Lost capture\n");
+ //Console.Write("Lost capture\n");
return;
}
- else
+ /*else
{
Console.Write("Have capture\n");
- }
+ } */
/* Get our most recent page */
var pageinfo = m_textSelect[m_textSelect.Count - 1];
page_num = pageinfo.pagenum;
@@ -3423,7 +3545,7 @@ namespace gsview
}
- private void ExtractPages(object sender, RoutedEventArgs e)
+ private void SaveXML(object sender, RoutedEventArgs e)
{
}
diff --git a/platform/winrt/gsview/PageExtractSave.xaml b/platform/winrt/gsview/PageExtractSave.xaml
new file mode 100644
index 00000000..cbc57522
--- /dev/null
+++ b/platform/winrt/gsview/PageExtractSave.xaml
@@ -0,0 +1,59 @@
+<Window x:Class="gsview.PageExtractSave"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ Title="Extract/Rearrange Pages" Height="306" Width="282">
+
+ <DockPanel LastChildFill="True">
+ <Grid x:Name="xaml_PageGrid" Width="100" Background="DarkGray" DockPanel.Dock="Left" Visibility="Visible">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+ <TextBlock Grid.Column="0" Grid.Row="0" Margin="15,0,0,0">
+ <Bold>Pages:</Bold>
+ </TextBlock>
+ <ListView Grid.Column="0" Grid.Row="1" x:Name="xaml_PageList" HorizontalAlignment="Stretch"
+ ScrollViewer.CanContentScroll="False"
+ Background="White" ScrollViewer.PanningMode="Both" Margin="10,5,10,10"
+ PreviewMouseLeftButtonDown="ExtractLeftButtonDown" PreviewMouseLeftButtonUp="ExtractLeftButtonUp"
+ PreviewMouseMove="ExtractMouseMove" MouseLeave="ExtractMouseLeave" PreviewMouseRightButtonDown="RightButtonDown">
+ <ListView.ItemTemplate>
+ <DataTemplate>
+ <StackPanel Margin="5,5,0,0" HorizontalAlignment="Left">
+ <TextBlock TextWrapping="Wrap" Text="{Binding PageString}" FontFamily="Segoe UI" FontSize="11" />
+ </StackPanel>
+ </DataTemplate>
+ </ListView.ItemTemplate>
+ </ListView>
+ </Grid>
+
+ <Grid Background="DarkGray" Grid.Row="0" Grid.Column="1" Margin="0,0,0,0">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+
+ <Button Grid.Column="0" Grid.Row="0" Width="70" Height="20" Name="xaml_AllPages" Click="AllPages" Margin="0,40,0,0">
+ <TextBlock>All Pages</TextBlock>
+ </Button>
+ <Button Grid.Column="0" Grid.Row="1" Width="70" Height="20" Name="xaml_EvenPages" Click="EvenPages" Margin="0,5,0,0">
+ <TextBlock>Even Pages</TextBlock>
+ </Button>
+ <Button Grid.Column="0" Grid.Row="2" Width="70" Height="20" Name="xaml_OddPages" Click="OddPages" Margin="0,5,0,0">
+ <TextBlock>Odd Pages</TextBlock>
+ </Button>
+ <Button Grid.Column="0" Grid.Row="3" Width="70" Height="20" Name="xaml_ReversePages" Click="Reverse" Margin="0,5,0,0">
+ <TextBlock>Reverse</TextBlock>
+ </Button>
+ <Button Grid.Column="0" Grid.Row="4" Width="70" Height="20" Name="xaml_Extract" Click="ExtractPages" Margin="0,20,0,0">
+ <TextBlock>Extract</TextBlock>
+ </Button>
+ <TextBlock Grid.Column="0" Grid.Row="5" Margin="0,20,0,0"> Use drag/drop to rearrange. <LineBreak /> Right click to delete from list.
+ <LineBreak /> Only selected pages extracted. </TextBlock>
+ </Grid>
+ </DockPanel>
+</Window>
diff --git a/platform/winrt/gsview/PageExtractSave.xaml.cs b/platform/winrt/gsview/PageExtractSave.xaml.cs
new file mode 100644
index 00000000..445141f7
--- /dev/null
+++ b/platform/winrt/gsview/PageExtractSave.xaml.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using System.ComponentModel;
+using System.Collections.ObjectModel;
+
+namespace gsview
+{
+ public partial class PageExtractSave : Window
+ {
+ public List<SelectPage> Pages;
+ SelectPage selectedpage = null;
+ int dropafterposition;
+ bool putattop = false;
+
+ /* Callback to Main */
+ internal delegate void ExtractCallBackMain(object gsObject);
+ internal event ExtractCallBackMain ExtractMain;
+
+ public PageExtractSave(int num_pages)
+ {
+ InitializeComponent();
+ Pages = new List<SelectPage>();
+ SetPageList(num_pages);
+ xaml_PageList.ItemsSource = Pages;
+ }
+
+ private void AllPages(object sender, RoutedEventArgs e)
+ {
+ xaml_PageList.SelectAll();
+ }
+
+ public void SetPageList(int num_pages)
+ {
+ for (int k = 1; k < num_pages + 1; k++)
+ {
+ SelectPage Spage = new SelectPage();
+ Spage.Page = k;
+ Spage.PageString = k;
+ Pages.Add(Spage);
+ }
+ }
+
+ private void EvenPages(object sender, RoutedEventArgs e)
+ {
+ /* First check if any are selected */
+ var item = xaml_PageList.SelectedItem;
+
+ /* If none are selected then get all the evens. otherwise just get
+ * all the evens of the pages that have been selected */
+ if (item == null)
+ {
+ /* Turn on the evens */
+ for (int kk = 1; kk < Pages.Count; kk = kk + 2)
+ (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = true;
+ }
+ else
+ {
+ /* Turn off any odds */
+ for (int kk = 0; kk < Pages.Count; kk = kk + 2)
+ (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = false;
+ }
+ }
+
+ private void OddPages(object sender, RoutedEventArgs e)
+ {
+ /* First check if any are selected */
+ var item = xaml_PageList.SelectedItem;
+
+ /* If none are selected then get all the odds. otherwise just get
+ all the odds of the pages that have been selected */
+ if (item == null)
+ {
+ /* Turn on the odds */
+ for (int kk = 0; kk < Pages.Count; kk = kk + 2)
+ (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = true;
+ }
+ else
+ {
+ /* Turn off any evens */
+ for (int kk = 1; kk < Pages.Count; kk = kk + 2)
+ (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = false;
+ }
+ }
+
+ private void ExtractPages(object sender, RoutedEventArgs e)
+ {
+ ExtractMain(this);
+ }
+
+ private void ExtractLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ int index = GetCurrentIndex();
+ if (index > -1 && index < Pages.Count)
+ selectedpage = Pages[index];
+ }
+
+ private void ExtractLeftButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ /* Check if we have something selected */
+ if (selectedpage == null)
+ {
+ Cursor = Cursors.Arrow;
+ return;
+ }
+
+ Point posit = e.GetPosition(xaml_PageList);
+ dropafterposition = GetCurrentIndex();
+ putattop = false;
+
+ if (dropafterposition < 0)
+ {
+ /* Check if we are above or below */
+ if (posit.Y < 0)
+ putattop = true;
+ else
+ dropafterposition = xaml_PageList.Items.Count - 1;
+ }
+ Cursor = Cursors.Arrow;
+ MoveItem();
+ selectedpage = null;
+ }
+
+ private void MoveItem()
+ {
+ if (putattop)
+ {
+ Pages.Remove(selectedpage);
+ Pages.Insert(0, selectedpage);
+ }
+ else
+ {
+ Pages.Remove(selectedpage);
+ Pages.Insert(dropafterposition, selectedpage);
+ }
+ xaml_PageList.Items.Refresh();
+ }
+
+ private void ExtractMouseMove(object sender, MouseEventArgs e)
+ {
+ if (Mouse.LeftButton == MouseButtonState.Pressed)
+ Cursor = Cursors.Hand;
+ }
+
+ private void ExtractMouseLeave(object sender, MouseEventArgs e)
+ {
+ Cursor = Cursors.Arrow;
+ }
+
+ private void RightButtonDown(object sender, MouseButtonEventArgs e)
+ {
+ var contextmenu = new System.Windows.Controls.ContextMenu();
+ this.ContextMenu = contextmenu;
+
+ var m1 = new System.Windows.Controls.MenuItem();
+ m1.Header = "Delete";
+ m1.Click += cntxDeleteItem;
+ contextmenu.Items.Add(m1);
+ }
+
+ /* Delete all selected items */
+ private void cntxDeleteItem(object sender, RoutedEventArgs e)
+ {
+ /* Go backwards */
+ var temp = xaml_PageList.SelectedItems;
+ int max = temp.Count; ;
+ for (int i = 0; i < max; i++)
+ {
+ var item = temp[i];
+ Pages.Remove((SelectPage)item);
+ }
+ xaml_PageList.Items.Refresh();
+ }
+
+ int GetCurrentIndex()
+ {
+ int index = -1;
+ for (int i = 0; i < this.xaml_PageList.Items.Count; ++i)
+ {
+ ListViewItem item = GetListViewItem(i);
+ if (item.IsMouseOver)
+ {
+ index = i;
+ break;
+ }
+ }
+ return index;
+ }
+
+ ListViewItem GetListViewItem(int index)
+ {
+ if (this.xaml_PageList.ItemContainerGenerator.Status !=
+ System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
+ return null;
+ return this.xaml_PageList.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
+ }
+
+ private void Reverse(object sender, RoutedEventArgs e)
+ {
+ Pages.Reverse();
+ xaml_PageList.Items.Refresh();
+ }
+ }
+}
diff --git a/platform/winrt/gsview/ghostsharp.cs b/platform/winrt/gsview/ghostsharp.cs
index 5922ee00..0d52dca8 100644
--- a/platform/winrt/gsview/ghostsharp.cs
+++ b/platform/winrt/gsview/ghostsharp.cs
@@ -12,11 +12,16 @@ namespace gsview
{
/* Warning. This list is in a particular order. The devices before
* psdrgb do not support multiple pages. Those including psdrgb do
- * support multiple pages. This is used in the conversion process */
+ * support multiple pages. This is used in the conversion process.
+ * Also note that mupdf devices go at the beginning of the list */
public enum gsDevice_t
{
- bmp16,
+ svg,
+ pnm,
+ pclbitmap,
+ pwg,
+ bmp16, /* Add mupdf devices before this one */
bmp16m,
bmp256,
bmp32b,
@@ -37,7 +42,7 @@ namespace gsview
pnggray,
pngmono,
psdcmyk,
- psdrgb, /* Add single page devices before this device */
+ psdrgb, /* Add single page gs devices before this device */
pdfwrite,
ps2write,
pxlcolor,
diff --git a/platform/winrt/gsview/gsview.csproj b/platform/winrt/gsview/gsview.csproj
index 707fdc05..fc9f6ddd 100644
--- a/platform/winrt/gsview/gsview.csproj
+++ b/platform/winrt/gsview/gsview.csproj
@@ -98,6 +98,9 @@
<Compile Include="OutputIntent.xaml.cs">
<DependentUpon>OutputIntent.xaml</DependentUpon>
</Compile>
+ <Compile Include="PageExtractSave.xaml.cs">
+ <DependentUpon>PageExtractSave.xaml</DependentUpon>
+ </Compile>
<Compile Include="Password.xaml.cs">
<DependentUpon>Password.xaml</DependentUpon>
</Compile>
@@ -141,6 +144,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="PageExtractSave.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Password.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
diff --git a/platform/winrt/gsview/mudocument.cs b/platform/winrt/gsview/mudocument.cs
index be8e4b50..404a0777 100644
--- a/platform/winrt/gsview/mudocument.cs
+++ b/platform/winrt/gsview/mudocument.cs
@@ -7,12 +7,62 @@ using System.Threading;
using System.Runtime.InteropServices;
using System.Security;
using System.Windows;
+using System.ComponentModel;
/* This file contains the interface between the muctx cpp class, which
implements the mupdf calls and the .net managed code */
namespace gsview
{
+ /* Parameters for conversion */
+ public struct ConvertParams_t
+ {
+ public int resolution;
+ public gsDevice_t device;
+ public String outputfile;
+ public int num_pages;
+ public System.Collections.IList pages;
+ public int currpage;
+ public GS_Result_t result;
+ };
+
+ /* Must match enum in muctx.h */
+ enum mudevice_t
+ {
+ SVG_OUT,
+ PNM_OUT,
+ PCL_OUT,
+ PWG_OUT,
+ };
+
+ public class muPDFEventArgs : EventArgs
+ {
+ private bool m_completed;
+ private int m_progress;
+ private ConvertParams_t m_param;
+
+ public bool Completed
+ {
+ get { return m_completed; }
+ }
+
+ public ConvertParams_t Params
+ {
+ get { return m_param; }
+ }
+
+ public int Progress
+ {
+ get { return m_progress; }
+ }
+
+ public muPDFEventArgs(bool completed, int progress, ConvertParams_t param)
+ {
+ m_completed = completed;
+ m_progress = progress;
+ m_param = param;
+ }
+ }
public struct content_s
{
@@ -24,6 +74,12 @@ namespace gsview
class mudocument
{
IntPtr mu_object;
+ BackgroundWorker m_worker;
+ ConvertParams_t m_params;
+ /* Callbacks to Main */
+ internal delegate void mupdfCallBackMain(object gsObject, muPDFEventArgs info);
+ internal event mupdfCallBackMain mupdfUpdateMain;
+
private System.Object m_lock = new System.Object();
public List<ContentItem> contents;
@@ -147,6 +203,17 @@ namespace gsview
int line_num, int item_num, ref double top_x,
ref double top_y, ref double height, ref double width);
+ [DllImport("mupdfnet.dll", CharSet = CharSet.Auto,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int mExtractPages(String infile, String outfile,
+ String password, bool has_password, bool linearize, int num_pages,
+ IntPtr pages);
+
+ [DllImport("mupdfnet.dll", CharSet = CharSet.Auto,
+ CallingConvention = CallingConvention.StdCall)]
+ public static extern int mSavePage(IntPtr ctx, String outfile,
+ int page_num, int res, int type, bool append);
+
public status_t Initialize()
{
mu_object = mInitialize();
@@ -423,5 +490,178 @@ namespace gsview
{
mReleaseText(mu_object, textpage);
}
+
+ public void PDFExtract(String infile, String outfile, String password,
+ bool has_password, bool linearize, int num_pages, System.Collections.IList pages)
+ {
+ if (num_pages > 0)
+ {
+ /* We need to do an allocation for our array of page numbers and
+ * perform pinning to avoid GC while in the c++ code */
+ GCHandle pagesPtrStable;
+ int[] page_list;
+ page_list = new int[pages.Count];
+
+ for (int kk = 0; kk < pages.Count; kk++)
+ {
+ SelectPage currpage = (SelectPage)pages[kk];
+ page_list[kk] = currpage.Page;
+ }
+ pagesPtrStable = GCHandle.Alloc(page_list, GCHandleType.Pinned);
+ mExtractPages(infile, outfile, password, has_password, linearize,
+ num_pages, pagesPtrStable.AddrOfPinnedObject());
+ pagesPtrStable.Free();
+ }
+ else
+ {
+ mExtractPages(infile, outfile, password, has_password, linearize,
+ num_pages, IntPtr.Zero);
+ }
+ }
+
+ public gsStatus ConvertSave(gsDevice_t device, String outputFile, int num_pages,
+ System.Collections.IList pages, int resolution)
+ {
+ ConvertParams_t convertparams = new ConvertParams_t();
+
+ convertparams.device = device;
+ convertparams.outputfile = outputFile;
+ convertparams.num_pages = num_pages;
+ convertparams.resolution = resolution;
+ convertparams.pages = pages;
+ convertparams.currpage = 1;
+ return ConvertMuPDF(convertparams);
+ }
+
+ /* Render page by page in background with progress call back */
+ private gsStatus ConvertMuPDF(ConvertParams_t Params)
+ {
+ try
+ {
+ if (m_worker != null && m_worker.IsBusy)
+ {
+ m_worker.CancelAsync();
+ return gsStatus.GS_BUSY;
+ }
+ if (m_worker == null)
+ {
+ m_worker = new BackgroundWorker();
+ m_worker.WorkerReportsProgress = true;
+ m_worker.WorkerSupportsCancellation = true;
+ m_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MuPDFCompleted);
+ m_worker.ProgressChanged += new ProgressChangedEventHandler(MuPDFProgressChanged);
+ m_worker.DoWork += new DoWorkEventHandler(MuPDFWork);
+ }
+
+ m_params = Params;
+ m_worker.RunWorkerAsync(Params);
+ return gsStatus.GS_READY;
+ }
+ catch (OutOfMemoryException e)
+ {
+ Console.WriteLine("Memory allocation failed during mupdf rendering\n");
+ return gsStatus.GS_ERROR;
+ }
+ }
+
+ private void MuPDFCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ ConvertParams_t Value;
+ muPDFEventArgs info;
+
+ if (e.Cancelled)
+ {
+ Value = new ConvertParams_t();
+ Value.result = GS_Result_t.gsCANCELLED;
+ info = new muPDFEventArgs(true, 100, Value);
+ }
+ else
+ {
+ Value = (ConvertParams_t)e.Result;
+ info = new muPDFEventArgs(true, 100, Value);
+ }
+ mupdfUpdateMain(this, info);
+ }
+
+ private void MuPDFProgressChanged(object sender, ProgressChangedEventArgs e)
+ {
+ /* Callback with progress */
+ ConvertParams_t Value = new ConvertParams_t();
+ muPDFEventArgs info = new muPDFEventArgs(false, e.ProgressPercentage, Value);
+ mupdfUpdateMain(this, info);
+ }
+
+ public void Cancel()
+ {
+ m_worker.CancelAsync();
+ }
+
+ /* ToDo: do we report pages that failed? or just push on */
+ private void MuPDFWork(object sender, DoWorkEventArgs e)
+ {
+ ConvertParams_t muparams = (ConvertParams_t)e.Argument;
+ String out_file = muparams.outputfile;
+ int num_pages = muparams.num_pages;
+ int resolution = muparams.resolution;
+ var pages = muparams.pages;
+ BackgroundWorker worker = sender as BackgroundWorker;
+
+ muparams.result = GS_Result_t.gsOK;
+
+ int result;
+
+ for (int kk = 0; kk < num_pages; kk++)
+ {
+ SelectPage curr_page = (SelectPage)pages[kk];
+ int page_num = curr_page.Page;
+ bool append = (kk != 0);
+
+ /* Look for file extension. */
+ string extension = System.IO.Path.GetExtension(out_file);
+ int len = extension.Length;
+ String new_out_file = out_file.Substring(0, out_file.Length - len);
+ String out_file_name = new_out_file + "_" + page_num + extension;
+
+ /* Question: is lock valid when done from this worker thread? */
+ switch (muparams.device)
+ {
+ case gsDevice_t.svg:
+ lock (this.m_lock) /* Single-page format */
+ result = mSavePage(mu_object, out_file_name,
+ page_num - 1, resolution, (int) mudevice_t.SVG_OUT,
+ false);
+ break;
+ case gsDevice_t.pnm:
+ lock (this.m_lock) /* Single-page format */
+ result = mSavePage(mu_object, out_file_name,
+ page_num - 1, resolution, (int)mudevice_t.PNM_OUT,
+ false);
+ break;
+ case gsDevice_t.pclbitmap: /* Multi-page format */
+ lock (this.m_lock)
+ result = mSavePage(mu_object, out_file,
+ page_num - 1, resolution, (int)mudevice_t.PCL_OUT,
+ append);
+ break;
+ case gsDevice_t.pwg: /* Multi-page format */
+ lock (this.m_lock)
+ result = mSavePage(mu_object, out_file,
+ page_num - 1, resolution, (int)mudevice_t.PWG_OUT,
+ append);
+ break;
+ }
+ double prog = (double) (kk+1.0)/((double) num_pages) * 100.0;
+ worker.ReportProgress((int)prog);
+
+ if (worker.CancellationPending == true)
+ {
+ e.Cancel = true;
+ muparams.result = GS_Result_t.gsCANCELLED;
+ break;
+ }
+ }
+ e.Result = muparams;
+ return;
+ }
}
}
diff --git a/platform/winrt/libmupdf_winRT.vcxproj b/platform/winrt/libmupdf_winRT.vcxproj
index c8adbcd5..1cee1c4d 100644
--- a/platform/winrt/libmupdf_winRT.vcxproj
+++ b/platform/winrt/libmupdf_winRT.vcxproj
@@ -158,7 +158,6 @@
<ClCompile Include="..\..\source\pdf\pdf-xref.c" />
<ClCompile Include="..\..\source\tiff\mutiff.c" />
<ClCompile Include="..\..\source\tools\pdfclean.c" />
- <ClCompile Include="..\..\source\tools\pdfinfo.c" />
<ClCompile Include="..\..\source\xps\xps-common.c" />
<ClCompile Include="..\..\source\xps\xps-doc.c" />
<ClCompile Include="..\..\source\xps\xps-glyphs.c" />
@@ -215,6 +214,7 @@
<ClInclude Include="..\..\include\mupdf\fitz\xml.h" />
<ClInclude Include="..\..\include\mupdf\img.h" />
<ClInclude Include="..\..\include\mupdf\memento.h" />
+ <ClInclude Include="..\..\include\mupdf\pdf-tools.h" />
<ClInclude Include="..\..\include\mupdf\pdf.h" />
<ClInclude Include="..\..\include\mupdf\pdf\annot.h" />
<ClInclude Include="..\..\include\mupdf\pdf\appearance.h" />
diff --git a/platform/winrt/libmupdf_winRT.vcxproj.filters b/platform/winrt/libmupdf_winRT.vcxproj.filters
index a5e907aa..f1d09539 100644
--- a/platform/winrt/libmupdf_winRT.vcxproj.filters
+++ b/platform/winrt/libmupdf_winRT.vcxproj.filters
@@ -426,9 +426,6 @@
<ClCompile Include="..\..\source\tools\pdfclean.c">
<Filter>tools</Filter>
</ClCompile>
- <ClCompile Include="..\..\source\tools\pdfinfo.c">
- <Filter>tools</Filter>
- </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\source\fitz\ucdn.h">
@@ -632,5 +629,8 @@
<ClInclude Include="..\..\source\pdf\pdf-interpret-imp.h">
<Filter>pdf</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\mupdf\pdf-tools.h">
+ <Filter>!include</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/platform/winrt/mupdfnet/mupdfnet.cpp b/platform/winrt/mupdfnet/mupdfnet.cpp
index d1a53454..0a582c7b 100644
--- a/platform/winrt/mupdfnet/mupdfnet.cpp
+++ b/platform/winrt/mupdfnet/mupdfnet.cpp
@@ -333,3 +333,95 @@ SYMBOL_DECLSPEC int __stdcall mGetTextCharacter(void *page, int block_num, int l
return cab.c;
}
+
+/* pdf clean methods */
+SYMBOL_DECLSPEC int __stdcall mExtractPages(PCWSTR infile, PCWSTR outfile,
+ PCWSTR password, bool has_password, bool linearize, int num_pages, void *pages)
+{
+ int argc = 3 + ((has_password) ? (2) : (0)) + ((linearize) ? (1) : (0)) + ((num_pages > 0) ? (1) : (0));
+ char **argv;
+ int size_pages;
+ char *infilechar = String_to_char(infile);
+ char *outfilechar = String_to_char(outfile);
+ char *passchar;
+ int *pagenum = (int*) pages;
+ char *pagenums;
+ char* num;
+ int num_size;
+ int result;
+ int pos = 1;
+
+ argv = new char*[argc];
+
+ if (has_password)
+ {
+ passchar = String_to_char(password);
+ argv[pos++] = "-p";
+ argv[pos++] = passchar;
+ }
+ if (linearize)
+ {
+ argv[pos++] = "-l";
+ }
+
+ argv[pos++] = infilechar;
+ argv[pos++] = outfilechar;
+
+ if (num_pages > 0)
+ {
+ /* Get last page, for number length and number of pages */
+ int last = pagenum[num_pages - 1];
+ if (last == 0)
+ {
+ num_size = 1;
+ size_pages = num_size;
+ }
+ else
+ {
+ num_size = floor(log10(last)) + 1;
+ size_pages = (num_size + 1) * num_pages;
+ }
+
+ /* Create the list of page numbers */
+ pagenums = new char[size_pages + 1];
+ pagenums[0] = '\0';
+ num = new char[num_size + 2];
+ for (int kk = 0; kk < num_pages; kk++)
+ {
+ if (kk < num_pages - 1)
+ sprintf(num, "%d,", pagenum[kk]);
+ else
+ sprintf(num, "%d", pagenum[kk]);
+ strcat(pagenums, num);
+ }
+ argv[pos++] = pagenums;
+ }
+
+
+ result = pdfclean_main(argc, argv);
+
+ delete(num);
+ delete(infilechar);
+ delete(outfilechar);
+ if (has_password)
+ delete(passchar);
+ if (num_pages > 0)
+ delete(pagenums);
+ delete(argv);
+ return result;
+}
+
+/* output methods */
+SYMBOL_DECLSPEC int __stdcall mSavePage(void *ctx, PCWSTR outfile, int page_num,
+ int resolution, int type, bool append)
+{
+ muctx *mu_ctx = static_cast<muctx*>(ctx);
+ char *outfilechar = String_to_char(outfile);
+ status_t result = mu_ctx->SavePage(outfilechar, page_num, resolution, type,
+ append);
+ delete(outfilechar);
+ if (result == S_ISOK)
+ return 0;
+ else
+ return -1;
+}
diff --git a/platform/winrt/mupdfnet/mupdfnet.h b/platform/winrt/mupdfnet/mupdfnet.h
index 34d4a034..0d873a77 100644
--- a/platform/winrt/mupdfnet/mupdfnet.h
+++ b/platform/winrt/mupdfnet/mupdfnet.h
@@ -61,4 +61,11 @@ EXTERN_C SYMBOL_DECLSPEC int __stdcall mGetTextCharacter(void *text, int block_n
int line_num, int item_num, double *top_x, double *top_y, double *height,
double *width);
-EXTERN_C SYMBOL_DECLSPEC void __stdcall mReleaseText(void *ctx, void *page); \ No newline at end of file
+EXTERN_C SYMBOL_DECLSPEC void __stdcall mReleaseText(void *ctx, void *page);
+
+/* pdfclean methods */
+EXTERN_C SYMBOL_DECLSPEC int __stdcall mExtractPages(PCWSTR infile, PCWSTR outfile,
+ PCWSTR password, bool has_password, int num_pages, void *pages);
+/* output */
+EXTERN_C SYMBOL_DECLSPEC int __stdcall mSavePage(void *ctx, PCWSTR outfile, int page_num,
+ int resolution, int type, bool append);
diff --git a/platform/winrt/mupdfwinrt/muctx.cpp b/platform/winrt/mupdfwinrt/muctx.cpp
index 4dcb9423..f7dfd20b 100644
--- a/platform/winrt/mupdfwinrt/muctx.cpp
+++ b/platform/winrt/mupdfwinrt/muctx.cpp
@@ -220,7 +220,7 @@ int muctx::GetPageCount()
int muctx::MeasurePage(int page_num, point_t *size)
{
fz_rect rect;
- fz_page *page;
+ fz_page *page = NULL;
fz_rect *bounds;
fz_try(mu_ctx)
@@ -230,6 +230,10 @@ int muctx::MeasurePage(int page_num, point_t *size)
size->X = bounds->x1 - bounds->x0;
size->Y = bounds->y1 - bounds->y0;
}
+ fz_always(mu_ctx)
+ {
+ fz_free_page(mu_doc, page);
+ }
fz_catch(mu_ctx)
{
return E_FAIL;
@@ -697,3 +701,98 @@ void muctx::ReleaseText(void *text)
fz_text_page *text_page = (fz_text_page*) text;
fz_free_text_page(mu_ctx, text_page);
}
+
+/* To do: banding */
+status_t muctx::SavePage(char *filename, int page_num, int resolution, int type,
+ bool append)
+{
+ float zoom;
+ fz_matrix ctm;
+ fz_rect bounds, tbounds;
+ FILE *file = NULL;
+ fz_output *out = NULL;
+ fz_device *dev = NULL;
+ int width, height;
+ fz_display_list *dlist = NULL;
+ fz_page *page = NULL;
+ bool valid = true;
+ fz_pixmap *pix = NULL;
+ fz_irect ibounds;
+
+ fz_var(dev);
+ fz_var(page);
+ fz_var(dlist);
+ fz_var(pix);
+
+ fz_try(mu_ctx)
+ {
+ page = fz_load_page(mu_doc, page_num);
+ fz_bound_page(mu_doc, page, &bounds);
+ zoom = resolution / 72;
+ fz_scale(&ctm, zoom, zoom);
+ tbounds = bounds;
+ fz_transform_rect(&tbounds, &ctm);
+ fz_round_rect(&ibounds, &tbounds);
+
+ /* First see if we have this one in the cache */
+ dlist = page_cache->Use(page_num, &width, &height, mu_ctx);
+
+ if (type == SVG_OUT)
+ {
+ file = fopen(filename, "wb");
+ if (file == NULL)
+ fz_throw(mu_ctx, FZ_ERROR_GENERIC, "cannot open file '%s'", filename);
+ out = fz_new_output_with_file(mu_ctx, file);
+
+ dev = fz_new_svg_device(mu_ctx, out, tbounds.x1 - tbounds.x0, tbounds.y1 - tbounds.y0);
+ if (dlist != NULL)
+ fz_run_display_list(dlist, dev, &ctm, &tbounds, NULL);
+ else
+ fz_run_page(mu_doc, page, dev, &ctm, NULL);
+ }
+ else
+ {
+ pix = fz_new_pixmap_with_bbox(mu_ctx, fz_device_rgb(mu_ctx), &ibounds);
+ fz_pixmap_set_resolution(pix, resolution);
+ fz_clear_pixmap_with_value(mu_ctx, pix, 255);
+ dev = fz_new_draw_device(mu_ctx, pix);
+ if (dlist != NULL)
+ fz_run_display_list(dlist, dev, &ctm, &tbounds, NULL);
+ else
+ fz_run_page(mu_doc, page, dev, &ctm, NULL);
+ switch (type)
+ {
+ case PNM_OUT:
+ fz_write_pnm(mu_ctx, pix, filename);
+ break;
+ case PCL_OUT: /* This can do multi-page */
+ fz_pcl_options options;
+ fz_pcl_preset(mu_ctx, &options, "ljet4");
+ fz_write_pcl(mu_ctx, pix, filename, append, &options);
+ break;
+ case PWG_OUT: /* This can do multi-page */
+ fz_write_pwg(mu_ctx, pix, filename, append, NULL);
+ break;
+ }
+ }
+ }
+ fz_always(mu_ctx)
+ {
+ if (pix != NULL)
+ fz_drop_pixmap(mu_ctx, pix);
+ fz_free_device(dev);
+ fz_free_page(mu_doc, page);
+ if (dlist != NULL)
+ fz_drop_display_list(mu_ctx, dlist);
+ if (out != NULL)
+ {
+ fz_close_output(out);
+ fclose(file);
+ }
+ }
+ fz_catch(mu_ctx)
+ {
+ return E_FAILURE;
+ }
+ return S_ISOK;
+} \ No newline at end of file
diff --git a/platform/winrt/mupdfwinrt/muctx.h b/platform/winrt/mupdfwinrt/muctx.h
index 79607987..8db81f1d 100644
--- a/platform/winrt/mupdfwinrt/muctx.h
+++ b/platform/winrt/mupdfwinrt/muctx.h
@@ -8,11 +8,14 @@
#include "Cache.h"
extern "C" {
#include "mupdf/fitz.h"
+#include "mupdf/pdf-tools.h"
}
#define MAX_SEARCH 500
+enum { SVG_OUT, PNM_OUT, PCL_OUT, PWG_OUT };
+
typedef struct point_s
{
double X;
@@ -104,6 +107,9 @@ public:
void ReleaseText(void *text);
bool RequiresPassword(void);
bool ApplyPassword(char* password);
+ status_t SavePage(char *filename, int pagenum, int resolution, int type,
+ bool append);
+
#ifdef _WINRT_DLL
status_t InitializeStream(IRandomAccessStream^ readStream, char *ext);
#else