diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2014-04-24 22:58:57 -0700 |
---|---|---|
committer | Michael Vrhel <michael.vrhel@artifex.com> | 2014-09-09 16:39:34 -0700 |
commit | e3cd64f5b9db724368658b84f91027e7b53fe48a (patch) | |
tree | 26c5eec7e426b63ff9cbfce5f1c57446230dbb59 /platform | |
parent | 154922fa139a31768338eabcf87aa74871e85ece (diff) | |
download | mupdf-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.xaml | 13 | ||||
-rw-r--r-- | platform/winrt/gsview/Convert.xaml.cs | 31 | ||||
-rw-r--r-- | platform/winrt/gsview/MainWindow.xaml | 53 | ||||
-rw-r--r-- | platform/winrt/gsview/MainWindow.xaml.cs | 290 | ||||
-rw-r--r-- | platform/winrt/gsview/PageExtractSave.xaml | 59 | ||||
-rw-r--r-- | platform/winrt/gsview/PageExtractSave.xaml.cs | 214 | ||||
-rw-r--r-- | platform/winrt/gsview/ghostsharp.cs | 11 | ||||
-rw-r--r-- | platform/winrt/gsview/gsview.csproj | 7 | ||||
-rw-r--r-- | platform/winrt/gsview/mudocument.cs | 240 | ||||
-rw-r--r-- | platform/winrt/libmupdf_winRT.vcxproj | 2 | ||||
-rw-r--r-- | platform/winrt/libmupdf_winRT.vcxproj.filters | 6 | ||||
-rw-r--r-- | platform/winrt/mupdfnet/mupdfnet.cpp | 92 | ||||
-rw-r--r-- | platform/winrt/mupdfnet/mupdfnet.h | 9 | ||||
-rw-r--r-- | platform/winrt/mupdfwinrt/muctx.cpp | 101 | ||||
-rw-r--r-- | platform/winrt/mupdfwinrt/muctx.h | 6 |
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 |