diff options
Diffstat (limited to 'platform/winrt/gsview')
30 files changed, 2708 insertions, 61 deletions
diff --git a/platform/winrt/gsview/ContentEntry.cs b/platform/winrt/gsview/ContentEntry.cs new file mode 100644 index 00000000..68600170 --- /dev/null +++ b/platform/winrt/gsview/ContentEntry.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace gsview +{ + public class ContentEntry + { + public String Name + { + get; + set; + } + + public int PageNum + { + get; + set; + } + + public ContentEntry(String Name, int PageNum) + { + this.Name = Name; + this.PageNum = PageNum; + } + }; +} + diff --git a/platform/winrt/gsview/ContentItem.cs b/platform/winrt/gsview/ContentItem.cs new file mode 100644 index 00000000..a9e079c8 --- /dev/null +++ b/platform/winrt/gsview/ContentItem.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel; + +namespace gsview +{ + class ContentItem : INotifyPropertyChanged + { + + public int Page + { + get; + internal set; + } + + public String StringMargin + { + get; + internal set; + } + + public ContentItem() + { + StringMargin = ""; + Page = 0; + } + + public event PropertyChangedEventHandler PropertyChanged; + + public void ContentRefresh() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("StringMargin")); + PropertyChanged(this, new PropertyChangedEventArgs("Page")); + } + } + } +} diff --git a/platform/winrt/gsview/Convert.xaml b/platform/winrt/gsview/Convert.xaml new file mode 100644 index 00000000..68a007d2 --- /dev/null +++ b/platform/winrt/gsview/Convert.xaml @@ -0,0 +1,113 @@ +<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"> + + <DockPanel LastChildFill="True"> + + <!-- Device viewer/selector --> + <Grid x:Name="xaml_DeviceGrid" 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>Devices:</Bold> + </TextBlock> + + <ListView Grid.Column="0" Grid.Row="1" x:Name="xaml_DeviceList" HorizontalAlignment="Stretch" + ScrollViewer.CanContentScroll="False" + Background="White" ScrollViewer.PanningMode="Both" Margin="10,5,10,10" SelectionMode="Single"> + <ListView.ItemTemplate> + <DataTemplate> + <StackPanel Margin="5,5,0,0" HorizontalAlignment="Left"> + <TextBlock TextWrapping="Wrap" Text="{Binding DeviceName}" FontFamily="Segoe UI" FontSize="11" /> + </StackPanel> + </DataTemplate> + </ListView.ItemTemplate> + </ListView> + </Grid> + + <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"> + <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> + + <!-- Buttons and extra options --> + <Grid Background="DarkGray" DockPanel.Dock="Left"> + <Grid.RowDefinitions> + <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" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + + <Grid Background="DarkGray" Grid.Row="0" Grid.Column="0" Margin="30,15,0,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + + <Button Grid.Column="0" Grid.Row="0" Width="50" Height="20" Name="xaml_Convert" Click="ConvertClick" Margin="0,0,0,0"> + <TextBlock>Convert</TextBlock> + </Button> + <Button Grid.Column="0" Grid.Row="1" Width="50" Height="20" Name="xaml_Cancel" Click="ConvertCancel" Margin="0,5,0,0"> + <TextBlock>Cancel</TextBlock> + </Button> + <Button Grid.Column="0" Grid.Row="2" Width="50" Height="20" Name="xaml_HelpConvert" Click="HelpConvert" Margin="0,5,0,0"> + <TextBlock>Help</TextBlock> + </Button> + </Grid> + + + <Grid Background="DarkGray" Grid.Row="0" Grid.Column="1" Margin="25,15,0,0"> + <Grid.RowDefinitions> + <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,0,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> + </Grid> + </Grid> + + + <TextBlock Grid.Column="0" Grid.Row="1" Margin="5,10,0,0"> + <Bold>Options:</Bold> + </TextBlock> + <TextBox Grid.Column="0" Grid.Row="2" Background="White" Height="40" Margin="5,5,5,5" Text=""></TextBox> + </Grid> + + + </DockPanel> +</Window> diff --git a/platform/winrt/gsview/Convert.xaml.cs b/platform/winrt/gsview/Convert.xaml.cs new file mode 100644 index 00000000..30c1b465 --- /dev/null +++ b/platform/winrt/gsview/Convert.xaml.cs @@ -0,0 +1,170 @@ +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 class Device : INotifyPropertyChanged + { + public String DeviceName + { + get; + internal set; + } + + public event PropertyChangedEventHandler PropertyChanged; + + public void PageRefresh() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("DeviceName")); + } + } + + public Device() + { + this.DeviceName = ""; + } + }; + + public class SelectPage : INotifyPropertyChanged + { + public int Page + { + get; + internal set; + } + + public int PageString + { + get; + internal set; + } + + public event PropertyChangedEventHandler PropertyChanged; + + public void PageRefresh() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("Page")); + } + } + }; + + + /// <summary> + /// Interaction logic for Convert.xaml + /// </summary> + public partial class Convert : Window + { + List<Device> GSDevices; + List<SelectPage> ConvertPages; + public Convert(int num_pages) + { + InitializeComponent(); + GSDevices = new List<Device>(); + ConvertPages = new List<SelectPage>(); + SetDeviceList(); + SetPageList(num_pages); + xaml_DeviceList.ItemsSource = GSDevices; + xaml_PageList.ItemsSource = ConvertPages; + } + + public void SetDeviceList() + { + foreach (gsDevice_t device in Enum.GetValues(typeof(gsDevice_t))) + { + Device device_t = new Device(); + device_t.DeviceName = Enum.GetName(typeof(gsDevice_t), device); + GSDevices.Add(device_t); + } + } + + 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; + ConvertPages.Add(Spage); + } + } + + private void ConvertClick(object sender, RoutedEventArgs e) + { + + } + + private void ConvertCancel(object sender, RoutedEventArgs e) + { + + } + + private void HelpConvert(object sender, RoutedEventArgs e) + { + + } + + private void AllPages(object sender, RoutedEventArgs e) + { + xaml_PageList.SelectAll(); + } + + 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 < ConvertPages.Count; kk = kk + 2) + (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = true; + } + else + { + /* Turn off any odds */ + for (int kk = 0; kk < ConvertPages.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 < ConvertPages.Count; kk = kk + 2) + (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = true; + } + else + { + /* Turn off any evens */ + for (int kk = 1; kk < ConvertPages.Count; kk = kk + 2) + (xaml_PageList.ItemContainerGenerator.ContainerFromIndex(kk) as ListViewItem).IsSelected = false; + } + } + } +} diff --git a/platform/winrt/gsview/DocPage.cs b/platform/winrt/gsview/DocPage.cs new file mode 100644 index 00000000..1cf55112 --- /dev/null +++ b/platform/winrt/gsview/DocPage.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel; +using System.Windows.Media.Imaging; +using System.Collections.ObjectModel; +using System.Windows.Media; + +namespace gsview +{ + public class DocPage : INotifyPropertyChanged + { + public int Height + { + get; + internal set; + } + + public int Width + { + get; + internal set; + } + + + public int NativeHeight + { + get; + set; + } + + public int NativeWidth + { + get; + set; + } + + public double Zoom + { + get; + set; + } + + public BitmapSource BitMap + { + get; + set; + } + + public List<RectList> TextBox + { + get; + set; + } + + public List<RectList> LinkBox + { + get; + set; + } + + public Page_Content_t Content + { + get; + set; + } + + public String PageName + { + get; + set; + } + + public int PageNum + { + get; + set; + } + + public event PropertyChangedEventHandler PropertyChanged; + + public void PageRefresh() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("BitMap")); + PropertyChanged(this, new PropertyChangedEventArgs("Height")); + PropertyChanged(this, new PropertyChangedEventArgs("Width")); + PropertyChanged(this, new PropertyChangedEventArgs("TextBox")); + } + } + + public DocPage() + { + this.Height = 0; + this.Width = 0; + this.NativeHeight = 0; + this.NativeWidth = 0; + this.Zoom = 0; + this.BitMap = null; + this.TextBox = null; + this.LinkBox = null; + this.Content = Page_Content_t.NOTSET; + this.PageNum = -1; + this.PageName = ""; + } + + public DocPage(int Height, int Width, double Zoom, BitmapSource BitMap, + List<RectList> TextBox, List<RectList> LinkBox, + Page_Content_t Content, int PageNum) + { + this.Height = Height; + this.Width = Width; + this.Zoom = Zoom; + this.BitMap = BitMap; + this.TextBox = TextBox; + this.LinkBox = LinkBox; + this.Content = Content; + this.PageNum = PageNum; + this.PageName = ("Page " + (PageNum + 1)); + } + }; + public class Pages : ObservableCollection<DocPage> + { + public Pages() + : base() + { + } + } +} diff --git a/platform/winrt/gsview/Links.cs b/platform/winrt/gsview/Links.cs new file mode 100644 index 00000000..822176d8 --- /dev/null +++ b/platform/winrt/gsview/Links.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Drawing; + +namespace gsview +{ + public enum link_t + { + LINK_GOTO = 0, + LINK_URI, + TEXTBOX, /* Do double duty with this class */ + NOT_SET, + }; + + class Links + { + link_t type; + //PointF upper_left; + //PointF lower_right; + Uri uri; + int page_num; + + public Links() + { + uri = new Uri(""); + page_num = -1; + type = link_t.NOT_SET; + } + } +} diff --git a/platform/winrt/gsview/MainWindow.xaml b/platform/winrt/gsview/MainWindow.xaml index 5706c547..47a1ef25 100644 --- a/platform/winrt/gsview/MainWindow.xaml +++ b/platform/winrt/gsview/MainWindow.xaml @@ -1,17 +1,74 @@ <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="350" Width="525"> -<!-- To do add in command short cuts and bindings --> - <Grid> - <Menu IsMainMenu="True"> + Title="gsview" Height="800" Width="650"> + + <Window.Resources> + <DataTemplate x:Key="PageTemplate"> + <Image Width="{Binding Width}" Height="{Binding Height}" Stretch="Fill" HorizontalAlignment="Center" Source="{Binding BitMap}" Margin="24,24,0,0"> + <Image.BitmapEffect> + <DropShadowBitmapEffect Color="Black" Direction="-50" + ShadowDepth="40" Softness=".7" /> + </Image.BitmapEffect> + </Image> + </DataTemplate> + + <Style TargetType="{x:Type Button}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type Button}"> + <ControlTemplate.Triggers> + <Trigger Property="IsPressed" Value="True"> + <Setter Property="Background" Value="Black" /> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + + <!-- Customize listview to turn off selection --> + <Style TargetType="{x:Type ListViewItem}"> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="{x:Type ListViewItem}"> + <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> + <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> + </Border> + <ControlTemplate.Triggers> + <Trigger Property="IsSelected" Value="true"> + <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/> + </Trigger> + <MultiTrigger> + <MultiTrigger.Conditions> + <Condition Property="IsSelected" Value="true"/> + <Condition Property="Selector.IsSelectionActive" Value="false"/> + </MultiTrigger.Conditions> + <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/> + </MultiTrigger> + <Trigger Property="IsEnabled" Value="false"> + <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> + </Trigger> + </ControlTemplate.Triggers> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + </Window.Resources> + + <!-- To do add in command short cuts and bindings --> + <DockPanel LastChildFill="True"> + <!-- Menu item at top --> + <Menu IsMainMenu="True" DockPanel.Dock="Top"> <MenuItem Header="_File"> <MenuItem Header="_Open..." Click="OpenFile"> <MenuItem.Icon> <Image Source="Resources/OpenFile.png" /> </MenuItem.Icon> </MenuItem> - <MenuItem Header="Save As..." > + <MenuItem Header="MuPDF Save As..." > <MenuItem.Icon> <Image Source="Resources/saveHS.png" /> </MenuItem.Icon> @@ -20,14 +77,14 @@ <MenuItem.Icon> <Image Source="Resources/Close.ico" /> </MenuItem.Icon> - </MenuItem> + </MenuItem> <MenuItem Header="Info"> <MenuItem.Icon> <Image Source="Resources/info.png" /> </MenuItem.Icon> </MenuItem> <Separator /> - <MenuItem Header="Convert..." > + <MenuItem Header="Ghostscript Convert..." Click="ConvertClick"> </MenuItem> <MenuItem Header="Extract..." > </MenuItem> @@ -40,7 +97,7 @@ </MenuItem.Icon> </MenuItem> <Separator /> - <MenuItem Header="Show Messages"> + <MenuItem Header="Show Messages" Click="ShowGSMessage"> <MenuItem.Icon> <Image Source="Resources/Message.png" /> </MenuItem.Icon> @@ -70,18 +127,306 @@ <MenuItem Header="Previous Page" /> <MenuItem Header="Goto Page" /> </MenuItem> + <MenuItem Header="_Options"> + <MenuItem Header="Ghostscript" /> + <MenuItem Header="Color" /> + </MenuItem> + <MenuItem Header="_Window" /> + <MenuItem Header="_Help" /> + </Menu> + + <!-- List of icons for page navigation, print, etc --> + <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Background="WhiteSmoke"> + <Button Width="20" Height="20" Name="BackPage" Click="OnBackPageClick" Background="Transparent" BorderBrush="Transparent" Margin="5,0,5,0"> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/Left.ico"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Width="20" Height="20" Name="ForwardPage2" Click="OnForwardPageClick" Background="Transparent" BorderBrush="Transparent"> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/Right.ico"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="ZoomIn" Background="Transparent" BorderBrush="Transparent"> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/zoom_in.ico"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="ZoomOut" Background="Transparent" BorderBrush="Transparent"> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/zoom_out.ico"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="ToggleThumbs" Background="Transparent" BorderBrush="Transparent"> + <Button.ToolTip> + <TextBlock Text="Thumbnails"/> + </Button.ToolTip> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/thumbnail.ico"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="ToggleContents" Background="Transparent" BorderBrush="Transparent"> + <Button.ToolTip> + <TextBlock Text="Contents"/> + </Button.ToolTip> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Rectangle Width="20" Height="20"> + <Rectangle.Fill> + <ImageBrush ImageSource="Resources/contents.ico"/> + </Rectangle.Fill> + </Rectangle> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="Search" Background="Transparent" BorderBrush="Transparent"> + <Button.ToolTip> + <TextBlock Text="Search"/> + </Button.ToolTip> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Rectangle Width="20" Height="20"> + <Rectangle.Fill> + <ImageBrush ImageSource="Resources/search.png"/> + </Rectangle.Fill> + </Rectangle> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="LinksToggle" Background="Transparent" BorderBrush="Transparent"> + <Button.ToolTip> + <TextBlock Text="Hyperlinks"/> + </Button.ToolTip> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Ellipse> + <Ellipse.Fill > + <ImageBrush ImageSource="Resources/hyperlink.png"/> + </Ellipse.Fill> + </Ellipse> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + <Button Margin="10 0 0 0" Width="20" Height="20" Click="Print" Background="Transparent" BorderBrush="Transparent"> + <Button.Template> + <ControlTemplate TargetType="{x:Type Button}"> + <Grid> + <Rectangle Width="20" Height="20"> + <Rectangle.Fill> + <ImageBrush ImageSource="Resources/printer.ico"/> + </Rectangle.Fill> + </Rectangle> + <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/> + </Grid> + </ControlTemplate> + </Button.Template> + </Button> + </StackPanel> + <!-- The progress bar that runs while the thumbnails are rendered --> + <Grid x:Name="xaml_ProgressGrid" DockPanel.Dock="Bottom" Visibility="Collapsed"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <ProgressBar x:Name="xaml_ThumbProgress" 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>Creating Thumbs</Bold></TextBlock> + <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Name="xaml_CancelThumb" Click="CancelLoadClick" 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 text search --> + <Grid x:Name="xaml_SearchGrid" DockPanel.Dock="Bottom" Visibility="Collapsed"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <ProgressBar x:Name="xaml_SearchProgress" 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>Searching</Bold></TextBlock> + <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Name="xaml_CancelSearch" Click="CancelSearchClick" 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 printing --> + <Grid x:Name="xaml_PrintGrid" DockPanel.Dock="Bottom" Visibility="Collapsed"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <ProgressBar x:Name="xaml_PrintProgress" 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>Printing</Bold></TextBlock> + <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Name="xaml_CancelPrint" Click="CancelPrintClick" 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> - <MenuItem Header="_Window" /> - <MenuItem Header="_Help" /> - </Menu> - + <!-- The progress bar that runs during distilling --> + <Grid x:Name="xaml_DistillGrid" DockPanel.Dock="Bottom" Visibility="Collapsed"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <ProgressBar x:Name="xaml_DistillProgress" 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>Distilling</Bold></TextBlock> + <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Name="xaml_CancelDistill" Click="CancelDistillClick" 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> + + <!-- Thumb viewer/selector --> + <Grid x:Name="xaml_ThumbGrid" Width="100" Background="DarkGray" DockPanel.Dock="Left" Visibility="Collapsed"> + <ListView x:Name="xaml_ThumbList" HorizontalAlignment="Stretch" + ItemTemplate="{StaticResource PageTemplate}" + ScrollViewer.CanContentScroll="False" + Background="DarkGray" ScrollViewer.PanningMode="Both" + PreviewMouseLeftButtonUp="ThumbSelected"> + </ListView> + </Grid> + <!-- Contents viewer/selector --> + <Grid x:Name="xaml_ContentGrid" Width="250" Background="DarkGray" DockPanel.Dock="Left" Visibility="Collapsed"> + <ListView x:Name="xaml_ContentList" HorizontalAlignment="Stretch" + ScrollViewer.CanContentScroll="False" PreviewMouseLeftButtonUp="ContentSelected" + Background="DarkGray" ScrollViewer.PanningMode="Both"> + <ListView.ItemTemplate> + <DataTemplate> + <StackPanel Margin="5,5,0,0" HorizontalAlignment="Left"> + <TextBlock TextWrapping="Wrap" Text="{Binding StringMargin}" FontFamily="Segoe UI" FontSize="11" /> + </StackPanel> + </DataTemplate> + </ListView.ItemTemplate> + </ListView> + </Grid> + <!-- Pages are last child fill. This goes in the center of our dock panel --> + <Grid x:Name="xaml_PageGrid" HorizontalAlignment="Stretch" Background="DarkGray" > + <ListView x:Name="xaml_PageList" HorizontalAlignment="Stretch" + ItemTemplate="{StaticResource PageTemplate}" + ScrollViewer.CanContentScroll="False" + Background="DarkGray" ScrollViewer.PanningMode="Both" + ScrollViewer.ScrollChanged="ListViewScrollChanged"> + <ListView.ItemContainerStyle> + <Style TargetType="ListViewItem"> + <Setter Property="HorizontalContentAlignment" Value="Stretch"/> + </Style> + </ListView.ItemContainerStyle> + </ListView> + </Grid> - </Grid> + </DockPanel> </Window> diff --git a/platform/winrt/gsview/MainWindow.xaml.cs b/platform/winrt/gsview/MainWindow.xaml.cs index 1e23d84e..71726468 100644 --- a/platform/winrt/gsview/MainWindow.xaml.cs +++ b/platform/winrt/gsview/MainWindow.xaml.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -13,9 +14,11 @@ using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Forms; -using mupdfwinrt; -using System.Threading.Tasks; -using System.Runtime.InteropServices.WindowsRuntime; +using System.ComponentModel; +using System.IO; +using System.Windows.Xps.Packaging; +using System.Printing; +using System.Windows.Markup; enum AppBar_t { @@ -37,7 +40,7 @@ enum RenderingStatus_t REN_PAGE /* Used to ignore value when source based setting */ }; -enum status_t +public enum status_t { S_ISOK, E_FAILURE, @@ -67,7 +70,7 @@ public struct spatial_info_t { public Point size; public double scale_factor; -} ; +}; /* C# has no defines.... */ static class Constants @@ -85,7 +88,7 @@ static class Constants public const int KEY_MINUS = 0xbd; public const int ZOOM_IN = 0; public const int ZOOM_OUT = 1; - public const double screenScale = 1; + public const double SCREEN_SCALE = 1; public const int HEADER_SIZE = 54; public const int SEARCH_FORWARD = 1; public const int SEARCH_BACKWARD = -1; @@ -97,8 +100,18 @@ namespace gsview /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> + /// + + public struct thumb_t + { + public int page_num; + public Byte[] bitmap; + public Point size; + } + public partial class MainWindow : Window { + mudocument mu_doc; public Pages m_docPages; List<DocPage> m_thumbnails; List<List<RectList>> m_page_link_list; @@ -108,37 +121,125 @@ namespace gsview List<RectList> m_text_list; private int m_rectlist_page; private List<ContentEntry> m_content_list; - mudocument mu_doc; private bool m_file_open; private int m_currpage; private int m_searchpage; private int m_num_pages; - private int m_slider_min; - private int m_slider_max; private bool m_init_done; - private bool m_flip_from_searchlink; private bool m_links_on; private int m_search_rect_count; private bool m_page_update; - WriteableBitmap m_BlankBmp; String m_textcolor; String m_linkcolor; RenderingStatus_t m_ren_status; - private bool m_insearch; /* Used for UI display */ - private bool m_search_active; /* Used to avoid multiple UI clicks */ - private bool m_sliderchange; - private double m_Progress; - int m_width; - int m_height; + private bool m_insearch; + private bool m_search_active; private bool m_handlingzoom; - private double m_panX; - private double m_panY; private bool m_have_thumbs; + private bool m_have_contents; + double m_doczoom; + ghostsharp m_ghostscript; + String m_currfile; + private gsprint m_ghostprint = null; + bool m_isXPS; + gsOutput m_gsoutput; + Convert m_convertwin; public MainWindow() { InitializeComponent(); + this.Closing += new System.ComponentModel.CancelEventHandler(Window_Closing); + m_file_open = false; + status_t result = CleanUp(); + + /* Allocations */ + try + { + m_docPages = new Pages(); + m_thumbnails = new List<DocPage>(); + m_page_link_list = new List<List<RectList>>(); + m_text_list = new List<RectList>(); + m_linkset = new List<bool>(); + m_ghostscript = new ghostsharp(); + m_ghostscript.gsUpdateMain += new ghostsharp.gsCallBackMain(gsProgress); + m_gsoutput = new gsOutput(); + m_gsoutput.Activate(); + m_ghostscript.gsIOUpdateMain += new ghostsharp.gsIOCallBackMain(gsIO); + m_convertwin = null; + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed at initialization\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message); + } + } + + void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) + { + m_gsoutput.RealWindowClosing(); + } + + private status_t CleanUp() + { + m_init_done = false; + + /* Clear out everything */ + if (m_docPages != null && m_docPages.Count > 0) + m_docPages.Clear(); + if (m_thumbnails != null && m_thumbnails.Count > 0) + m_thumbnails.Clear(); + if (m_page_link_list != null && m_page_link_list.Count > 0) + m_page_link_list.Clear(); + if (m_text_list != null && m_text_list.Count > 0) + m_text_list.Clear(); + if (m_linkset != null && m_linkset.Count > 0) + m_linkset.Clear(); + + if (mu_doc != null) + mu_doc.CleanUp(); + try + { + mu_doc = new mudocument(); + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed during clean up\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message); + } + status_t result = mu_doc.Initialize(); + + if (result != status_t.S_ISOK) + { + Console.WriteLine("Library allocation failed during clean up\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Library allocation failed!"); + return result; + } + + m_have_thumbs = false; m_file_open = false; + m_insearch = false; + m_search_active = false; + m_num_pages = -1; + m_search_rect_count = 0; + m_links_on = false; + m_rectlist_page = -1; + m_doczoom = 1.0; + m_isXPS = false; + return result; + } + + private void ShowMessage(NotifyType_t type, String Message) + { + if (type == NotifyType_t.MESS_ERROR) + { + // System.Windows.Forms.MessageBox.Show(Message, "Error", + // MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + } + else + { + // System.Windows.Forms.MessageBox.Show(Message, "Notice", + // MessageBoxButtons.OK); + } } private void CloseDoc() @@ -148,10 +249,155 @@ namespace gsview } + /* Set the page with the new raster information */ + private void UpdatePage(int page_num, Byte[] bitmap, Point ras_size, + Page_Content_t content, double zoom_in) + { + DocPage doc_page = this.m_docPages[page_num]; + + doc_page.Width = (int)ras_size.X; + doc_page.Height = (int)ras_size.Y; + + doc_page.Content = content; + doc_page.Zoom = zoom_in; + + int stride = doc_page.Width * 4; + doc_page.BitMap = BitmapSource.Create(doc_page.Width, doc_page.Height, 72, 72, PixelFormats.Pbgra32, BitmapPalettes.Halftone256, bitmap, stride); + doc_page.PageNum = page_num; + + if (content == Page_Content_t.THUMBNAIL) + { + doc_page.Width = (int)(ras_size.X / Constants.SCALE_THUMB); + doc_page.Height = (int)(ras_size.Y / Constants.SCALE_THUMB); + } + } + + void SetThumbInit(int page_num, Byte[] bitmap, Point ras_size, double zoom_in) + { + /* Two jobs. Store the thumb and possibly update the full page */ + DocPage doc_page = m_thumbnails[page_num]; + + doc_page.Width = (int)ras_size.X; + doc_page.Height = (int)ras_size.Y; + doc_page.Content = Page_Content_t.THUMBNAIL; + doc_page.Zoom = zoom_in; + int stride = doc_page.Width * 4; + doc_page.BitMap = BitmapSource.Create(doc_page.Width, doc_page.Height, 72, 72, PixelFormats.Pbgra32, BitmapPalettes.Halftone256, bitmap, stride); + doc_page.PageNum = page_num; + + /* And the main page */ + var doc = m_docPages[page_num]; + if (doc.Content == Page_Content_t.THUMBNAIL || doc.Content == Page_Content_t.FULL_RESOLUTION) + return; + else + { + doc_page = this.m_docPages[page_num]; + doc_page.Content = Page_Content_t.THUMBNAIL; + doc_page.Zoom = zoom_in; + + doc_page.BitMap = m_thumbnails[page_num].BitMap; + doc_page.Width = (int)(ras_size.X / Constants.SCALE_THUMB); + doc_page.Height = (int)(ras_size.Y / Constants.SCALE_THUMB); + doc_page.PageNum = page_num; + } + } + + private void ThumbsWork(object sender, DoWorkEventArgs e) + { + Point ras_size; + status_t code; + double scale_factor; + spatial_info_t spatial_info = InitSpatial(1); + BackgroundWorker worker = sender as BackgroundWorker; + + spatial_info.scale_factor = Constants.SCALE_THUMB; + Byte[] bitmap; + + for (int k = 0; k < m_num_pages; k++) + { + if (ComputePageSize(spatial_info, k, out ras_size, out scale_factor) == status_t.S_ISOK) + { + try + { + bitmap = new byte[(int)ras_size.X * (int)ras_size.Y * 4]; + /* Synchronous call on our background thread */ + code = (status_t) mu_doc.RenderPage(k, bitmap, (int)ras_size.X, (int)ras_size.Y, scale_factor, false, false); + } + catch (OutOfMemoryException em) + { + Console.WriteLine("Memory allocation failed thumb page " + k + em.Message + "\n"); + break; + } + /* Use thumb if we rendered ok */ + if (code == status_t.S_ISOK) + { + double percent = 100 * (double)(k + 1) / (double)m_num_pages; + thumb_t curr_thumb = new thumb_t(); + curr_thumb.page_num = k; + curr_thumb.bitmap = bitmap; + curr_thumb.size = ras_size; + worker.ReportProgress((int)percent, curr_thumb); + } + } + } + } + + private void ThumbsCompleted(object sender, RunWorkerCompletedEventArgs e) + { + xaml_ProgressGrid.Visibility = System.Windows.Visibility.Collapsed; + xaml_ThumbProgress.Value = 0; + xaml_ThumbList.ItemsSource = m_thumbnails; + m_have_thumbs = true; + } + + private void ThumbsProgressChanged(object sender, ProgressChangedEventArgs e) + { + thumb_t thumb = (thumb_t)(e.UserState); + + xaml_ThumbProgress.Value = e.ProgressPercentage; + SetThumbInit(thumb.page_num, thumb.bitmap, thumb.size, 1.0); + m_docPages[thumb.page_num].PageRefresh(); + m_thumbnails[thumb.page_num].PageRefresh(); + } + + private void RenderThumbs() + { + /* Create background task for rendering the thumbnails. Allow + this to be cancelled if we open a new doc while we are in loop + rendering. Put the UI updates in the progress changed which will + run on the main thread */ + try + { + BackgroundWorker worker = new BackgroundWorker(); + worker.WorkerReportsProgress = true; + worker.WorkerSupportsCancellation = true; + worker.DoWork += new DoWorkEventHandler(ThumbsWork); + worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ThumbsCompleted); + worker.ProgressChanged += new ProgressChangedEventHandler(ThumbsProgressChanged); + xaml_ProgressGrid.Visibility = System.Windows.Visibility.Visible; + worker.RunWorkerAsync(); + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed during thumb rendering\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message); + } + } + + private spatial_info_t InitSpatial(double scale) + { + spatial_info_t value = new spatial_info_t(); + + value.size.Y = this.ActualHeight; + value.size.X = this.ActualWidth; + value.scale_factor = scale; + return value; + } + private void OpenFile(object sender, RoutedEventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); - dlg.Filter = "Xps Documents (*.xps)|*.xps"; + dlg.Filter = "Document Files(*.ps;*.eps;*.pdf;*.xps;*.cbz)|*.ps;*.eps;*.pdf;*.xps;*.cbz|All files (*.*)|*.*"; dlg.FilterIndex = 1; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { @@ -159,38 +405,502 @@ namespace gsview { CloseDoc(); } - try + /* If we have a ps or eps file then launch the distiller first + * and then we will get a temp pdf file which will be opened by + * mupdf */ + string extension = System.IO.Path.GetExtension(dlg.FileName); + if (extension.ToUpper() == ".PS" || extension.ToUpper() == ".EPS") + { + xaml_DistillProgress.Value = 0; + if (m_ghostscript.DistillPS(dlg.FileName) == gsStatus.GS_BUSY) + { + ShowMessage(NotifyType_t.MESS_STATUS, "GS currently busy"); + return; + } + xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible; + return; + } + + /* Set if this is already xps for printing */ + if (extension.ToUpper() == ".XPS") + m_isXPS = true; + + StartViewer(dlg.FileName); + + } + } + + private void StartViewer(String File) + { + m_currfile = File; + status_t code = mu_doc.OpenFile(m_currfile); + if (code == status_t.S_ISOK) + { + InitialRender(); + RenderThumbs(); + m_file_open = true; + } + else + { + m_currfile = null; + ShowMessage(NotifyType_t.MESS_ERROR, "Failed to open file!"); + } + } + + private status_t ComputePageSize(spatial_info_t spatial_info, int page_num, + out Point render_size, out double scale_factor) + { + Point screenSize = new Point(); + Point renpageSize = new Point(); + + status_t code = (status_t)mu_doc.GetPageSize(page_num, out render_size); + if (code != status_t.S_ISOK) + { + scale_factor = 1.0; + return code; + } + + screenSize = spatial_info.size; + screenSize.Y *= Constants.SCREEN_SCALE; + screenSize.X *= Constants.SCREEN_SCALE; + + double hscale = screenSize.X / render_size.X; + double vscale = screenSize.Y / render_size.Y; + double scale = Math.Min(hscale, vscale); + renpageSize.X = (render_size.X * scale * spatial_info.scale_factor); + renpageSize.Y = (render_size.Y * scale * spatial_info.scale_factor); + + scale_factor = (scale * spatial_info.scale_factor); + render_size = renpageSize; + + return status_t.S_ISOK; + } + + private DocPage InitDocPage() + { + DocPage doc_page = new DocPage(); + + doc_page.BitMap = null; + doc_page.Height = Constants.BLANK_HEIGHT; + doc_page.Width = Constants.BLANK_WIDTH; + doc_page.NativeHeight = Constants.BLANK_HEIGHT; + doc_page.NativeWidth = Constants.BLANK_WIDTH; + doc_page.Content = Page_Content_t.DUMMY; + doc_page.TextBox = null; + doc_page.LinkBox = null; + return doc_page; + } + + async private void InitialRender() + { + m_num_pages = mu_doc.GetPageCount(); + m_currpage = 0; + + for (int k = 0; k < m_num_pages; k++) + { + m_docPages.Add(InitDocPage()); + m_thumbnails.Add(InitDocPage()); + /* Create empty lists for our links and specify that they have + not been computed for these pages */ + List<RectList> temp_link = new List<RectList>(); + m_page_link_list.Add(temp_link); + m_linkset.Add(false); + } + + /* Do the first few full res pages */ + spatial_info_t spatial_info = InitSpatial(1); + for (int k = 0; k < Constants.LOOK_AHEAD + 2; k++) + { + if (m_num_pages > k) { - OpenDocument(dlg.FileName); + Point ras_size; + double scale_factor; + + if (ComputePageSize(spatial_info, k, out ras_size, out scale_factor) == status_t.S_ISOK) + { + try + { + Byte[] bitmap = new byte[(int)ras_size.X * (int)ras_size.Y * 4]; + + Task<int> ren_task = + new Task<int>(() => mu_doc.RenderPage(k, bitmap, (int)ras_size.X, (int)ras_size.Y, scale_factor, false, true)); + ren_task.Start(); + await ren_task.ContinueWith((antecedent) => + { + status_t code = (status_t)ren_task.Result; + if (code == status_t.S_ISOK) + UpdatePage(k, bitmap, ras_size, Page_Content_t.FULL_RESOLUTION, 1.0); + }, TaskScheduler.FromCurrentSynchronizationContext()); + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed page " + k + "\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message); + } + } } - catch (UnauthorizedAccessException) + } + m_init_done = true; + xaml_PageList.ItemsSource = m_docPages; + } + + private void OnBackPageClick(object sender, RoutedEventArgs e) + { + if (m_currpage == 0) return; + + m_currpage = m_currpage - 1; + xaml_PageList.ScrollIntoView(m_docPages[m_currpage]); + } + + private void OnForwardPageClick(object sender, RoutedEventArgs e) + { + if (m_currpage == m_num_pages - 1) return; + + m_currpage = m_currpage + 1; + xaml_PageList.ScrollIntoView(m_docPages[m_currpage]); + } + + private void CancelLoadClick(object sender, RoutedEventArgs e) + { + /* Cancel during thumbnail loading. Deactivate the button + * and cancel the thumbnail rendering */ + } + + private void ToggleThumbs(object sender, RoutedEventArgs e) + { + if (m_have_thumbs) + { + if (xaml_ThumbGrid.Visibility == System.Windows.Visibility.Collapsed) { - System.Windows.MessageBox.Show( - String.Format("Unable to access {0}", dlg.FileName)); + xaml_ThumbGrid.Visibility = System.Windows.Visibility.Visible; + } + else + { + xaml_ThumbGrid.Visibility = System.Windows.Visibility.Collapsed; + } + } + } + + private void ToggleContents(object sender, RoutedEventArgs e) + { + if (xaml_ContentGrid.Visibility == System.Windows.Visibility.Visible) + { + xaml_ContentGrid.Visibility = System.Windows.Visibility.Collapsed; + return; + } + + if (m_num_pages < 0) + return; + + if (xaml_ContentList.Items.IsEmpty) + { + int size_content = mu_doc.ComputeContents(); + if (size_content == 0) + return; + xaml_ContentList.ItemsSource = mu_doc.contents; + } + xaml_ContentGrid.Visibility = System.Windows.Visibility.Visible; + } + + private void ThumbSelected(object sender, MouseButtonEventArgs e) + { + var item = ((FrameworkElement)e.OriginalSource).DataContext as DocPage; + if (item != null) + { + xaml_PageList.ScrollIntoView(m_docPages[item.PageNum]); + } + } + + private void ContentSelected(object sender, MouseButtonEventArgs e) + { + var item = ((FrameworkElement)e.OriginalSource).DataContext as ContentItem; + if (item != null && item.Page < m_num_pages) + { + xaml_PageList.ScrollIntoView(m_docPages[item.Page]); + } + } + + private void ListViewScrollChanged(object sender, ScrollChangedEventArgs e) + { + var lv = (System.Windows.Controls.ListView) sender; + foreach (var lvi in lv.Items) + { + var container = lv.ItemContainerGenerator.ContainerFromItem(lvi) as ListBoxItem; + if (container != null && Visible(container, lv)) + { + var found = container.Content; + if (found != null) + { + var Item = (DocPage)found; + RenderRange(Item.PageNum); + } return; } } } - private async void OpenDocument(String filename) + /* Render +/- the look ahead from where we are if blank page is present */ + async private void RenderRange(int curr_page) + { + spatial_info_t spatial_info = InitSpatial(m_doczoom); + int range = Constants.LOOK_AHEAD; + + range = 0; // debug + for (int k = curr_page - range; k <= curr_page + range; k++) + { + if (k >= 0 && k < m_num_pages) + { + /* Check if page is already rendered */ + var doc = m_docPages[k]; + if (doc.Content != Page_Content_t.FULL_RESOLUTION || + doc.Zoom != m_doczoom) + { + Point ras_size; + double scale_factor; + + if (ComputePageSize(spatial_info, k, out ras_size, out scale_factor) == status_t.S_ISOK) + { + try + { + Byte[] bitmap = new byte[(int)ras_size.X * (int)ras_size.Y * 4]; + + Task<int> ren_task = + new Task<int>(() => mu_doc.RenderPage(k, bitmap, (int)ras_size.X, (int)ras_size.Y, scale_factor, false, true)); + ren_task.Start(); + await ren_task.ContinueWith((antecedent) => + { + status_t code = (status_t)ren_task.Result; + if (code == status_t.S_ISOK) + { + UpdatePage(k, bitmap, ras_size, Page_Content_t.FULL_RESOLUTION, 1.0); + m_docPages[k].PageRefresh(); + } + }, TaskScheduler.FromCurrentSynchronizationContext()); + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed page " + k + "\n"); + ShowMessage(NotifyType_t.MESS_ERROR, "Out of memory: " + e.Message); + } + } + } + } + } + } + + private bool Visible(FrameworkElement elem, FrameworkElement cont) + { + if (!elem.IsVisible) + return false; + Rect rect = new Rect(0.0, 0.0, cont.ActualWidth, cont.ActualHeight); + Rect bounds = elem.TransformToAncestor(cont).TransformBounds(new Rect(0.0, 0.0, elem.ActualWidth, elem.ActualHeight)); + Rect bounds2 = new Rect(new Point(bounds.TopLeft.X, bounds.TopLeft.Y), new Point(bounds.BottomRight.X, bounds.BottomRight.Y - 5)); + return rect.Contains(bounds2.TopLeft) || rect.Contains(bounds2.BottomRight); + } + + private void ReleasePages(int old_page, int new_page) + { + if (old_page == new_page) return; + /* To keep from having memory issue reset the page back to + the thumb if we are done rendering the thumbnails */ + for (int k = old_page - Constants.LOOK_AHEAD; k <= old_page + Constants.LOOK_AHEAD; k++) + { + if (k < new_page - Constants.LOOK_AHEAD || k > new_page + Constants.LOOK_AHEAD) + { + if (k >= 0 && k < m_num_pages) + { + SetThumb(k); + } + } + } + } + + /* Return this page from a full res image to the thumb image or only set + to thumb if it has not already been set */ + private void SetThumb(int page_num) + { + /* See what is there now */ + var doc = m_docPages[page_num]; + if (doc.Content == Page_Content_t.THUMBNAIL && doc.Zoom == m_doczoom) return; + + if (m_thumbnails.Count > page_num) + { + m_page_update = true; + var thumb_page = m_thumbnails[page_num]; + thumb_page.Height = (int)(thumb_page.NativeHeight * m_doczoom); + thumb_page.Width = (int)(thumb_page.NativeWidth * m_doczoom); + thumb_page.Zoom = 1.0; + m_docPages[page_num] = thumb_page; + m_page_update = false; + } + } + + private void LinksToggle(object sender, RoutedEventArgs e) { - string target = "."; - char[] anyOf = target.ToCharArray(); - var index = filename.LastIndexOfAny(anyOf); - string extension = filename.Substring(index + 1); + } - int result = mu_doc.OpenFileName(filename, extension); + private void Search(object sender, RoutedEventArgs e) + { - //int result = await mu_doc.OpenFileAsync(filename, extension); - /* Check if we need password */ - //if (mu_doc.RequiresPassword()) - //{ - //SetView(view_t.VIEW_PASSWORD); - // return; - //} - //else - // InitialRender(); + } + + private void ZoomOut(object sender, RoutedEventArgs e) + { + + } + + private void ZoomIn(object sender, RoutedEventArgs e) + { + + } + + private void CancelSearchClick(object sender, RoutedEventArgs e) + { + + } + + private void gsIO(object gsObject, String mess, int len) + { + m_gsoutput.Update(mess, len); + } + + private void gsProgress(object gsObject, gsEventArgs asyncInformation) + { + if (asyncInformation.Completed) + { + xaml_DistillProgress.Value = 100; + xaml_DistillProgress.Visibility = System.Windows.Visibility.Collapsed; + if (asyncInformation.Params.result == GS_Result_t.gsFAILED) + { + switch (asyncInformation.Params.task) + { + case GS_Task_t.CREATE_XPS: + ShowMessage(NotifyType_t.MESS_STATUS, "Ghostscript failed to create XPS"); + break; + + case GS_Task_t.PS_DISTILL: + ShowMessage(NotifyType_t.MESS_STATUS, "Ghostscript failed to distill PS"); + break; + + case GS_Task_t.SAVE_RESULT: + + break; + } + return; + } + GSResult(asyncInformation.Params); + } + else + { + xaml_PrintProgress.Value = asyncInformation.Progress; + } + } + + /* GS Result*/ + public void GSResult(gsParams_t result) + { + switch (result.task) + { + case GS_Task_t.CREATE_XPS: + PrintXPS(result.outputfile); + break; + + case GS_Task_t.PS_DISTILL: + StartViewer(result.outputfile); + break; + + case GS_Task_t.SAVE_RESULT: + + break; + } + } + + + /* Printing is achieved using xpswrite device in ghostscript and + * pushing that file through the XPS print queue */ + private void Print(object sender, RoutedEventArgs e) + { + if (!m_file_open) + return; + + /* If file is already xps then gs need not do this */ + if (!m_isXPS) + { + xaml_DistillProgress.Value = 0; + if (m_ghostscript.CreateXPS(m_currfile) == gsStatus.GS_BUSY) + { + ShowMessage(NotifyType_t.MESS_STATUS, "GS currently busy"); + return; + } + else + { + xaml_DistillGrid.Visibility = System.Windows.Visibility.Visible; + } + + } + PrintXPS(m_currfile); + } + + private void PrintXPS(String file) + { + gsprint ghostprint = new gsprint(); + System.Windows.Controls.PrintDialog pDialog = ghostprint.GetPrintDialog(); + + if (pDialog == null) + return; + + XpsDocument xpsDocument = new XpsDocument(file, FileAccess.Read); + FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence(); + + PrintQueue printQueue = pDialog.PrintQueue; + + m_ghostprint = ghostprint; + xaml_PrintGrid.Visibility = System.Windows.Visibility.Visible; + m_ghostprint.PrintUpdate += new gsprint.AsyncPrintCallBack(PrintProgress); + + xaml_PrintProgress.Value = 0; + + ghostprint.Print(printQueue, fixedDocSeq); + } + + private void PrintProgress(object printHelper, gsPrintEventArgs asyncInformation) + { + if (asyncInformation.Completed) + { + xaml_PrintProgress.Value = 100; + xaml_PrintGrid.Visibility = System.Windows.Visibility.Collapsed; + } + else + { + xaml_PrintProgress.Value = 100 * (double) asyncInformation.Page / (double) m_num_pages; + } + } + + private void CancelDistillClick(object sender, RoutedEventArgs e) + { + + } + + private void CancelPrintClick(object sender, RoutedEventArgs e) + { + m_ghostprint.CancelAsync(); + } + + private void ShowGSMessage(object sender, RoutedEventArgs e) + { + m_gsoutput.Show(); + } + + private void ConvertClick(object sender, RoutedEventArgs e) + { + if (m_convertwin == null) + { + m_convertwin = new Convert(m_num_pages); + m_convertwin.Activate(); + m_convertwin.Show(); + } } } } + diff --git a/platform/winrt/gsview/Properties/AssemblyInfo.cs b/platform/winrt/gsview/Properties/AssemblyInfo.cs index 4cb76a71..77e3ac52 100644 --- a/platform/winrt/gsview/Properties/AssemblyInfo.cs +++ b/platform/winrt/gsview/Properties/AssemblyInfo.cs @@ -12,7 +12,7 @@ using System.Windows; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("gsview")] -[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/platform/winrt/gsview/RectList.cs b/platform/winrt/gsview/RectList.cs new file mode 100644 index 00000000..3c761876 --- /dev/null +++ b/platform/winrt/gsview/RectList.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace gsview +{ + public class RectList + { + public String Index + { + get; + set; + } + + public String Color + { + get; + set; + } + + public int Height + { + get; + set; + } + + public int Width + { + get; + set; + } + + public int X + { + get; + set; + } + + public int Y + { + get; + set; + } + + public int Type + { + get; + set; + } + + public int PageNum + { + get; + set; + } + + public Uri Urilink + { + get; + set; + } + } +} diff --git a/platform/winrt/gsview/Resources/Left.ico b/platform/winrt/gsview/Resources/Left.ico Binary files differnew file mode 100644 index 00000000..b2507e31 --- /dev/null +++ b/platform/winrt/gsview/Resources/Left.ico diff --git a/platform/winrt/gsview/Resources/Right.ico b/platform/winrt/gsview/Resources/Right.ico Binary files differnew file mode 100644 index 00000000..c2f9238f --- /dev/null +++ b/platform/winrt/gsview/Resources/Right.ico diff --git a/platform/winrt/gsview/Resources/contents.ico b/platform/winrt/gsview/Resources/contents.ico Binary files differnew file mode 100644 index 00000000..97a12dd8 --- /dev/null +++ b/platform/winrt/gsview/Resources/contents.ico diff --git a/platform/winrt/gsview/Resources/gsview.ico b/platform/winrt/gsview/Resources/gsview.ico Binary files differnew file mode 100644 index 00000000..65b8b6b9 --- /dev/null +++ b/platform/winrt/gsview/Resources/gsview.ico diff --git a/platform/winrt/gsview/Resources/gsview.png b/platform/winrt/gsview/Resources/gsview.png Binary files differnew file mode 100644 index 00000000..bfcfb8db --- /dev/null +++ b/platform/winrt/gsview/Resources/gsview.png diff --git a/platform/winrt/gsview/Resources/hyperlink.png b/platform/winrt/gsview/Resources/hyperlink.png Binary files differnew file mode 100644 index 00000000..6ea0d798 --- /dev/null +++ b/platform/winrt/gsview/Resources/hyperlink.png diff --git a/platform/winrt/gsview/Resources/printer.ico b/platform/winrt/gsview/Resources/printer.ico Binary files differindex 34a15747..c03d9853 100644 --- a/platform/winrt/gsview/Resources/printer.ico +++ b/platform/winrt/gsview/Resources/printer.ico diff --git a/platform/winrt/gsview/Resources/search.ico b/platform/winrt/gsview/Resources/search.ico Binary files differnew file mode 100644 index 00000000..2841a637 --- /dev/null +++ b/platform/winrt/gsview/Resources/search.ico diff --git a/platform/winrt/gsview/Resources/search.png b/platform/winrt/gsview/Resources/search.png Binary files differnew file mode 100644 index 00000000..9bbb2255 --- /dev/null +++ b/platform/winrt/gsview/Resources/search.png diff --git a/platform/winrt/gsview/Resources/thumbnail.ico b/platform/winrt/gsview/Resources/thumbnail.ico Binary files differnew file mode 100644 index 00000000..71d38e97 --- /dev/null +++ b/platform/winrt/gsview/Resources/thumbnail.ico diff --git a/platform/winrt/gsview/Resources/zoom_in.ico b/platform/winrt/gsview/Resources/zoom_in.ico Binary files differnew file mode 100644 index 00000000..b0ca2ead --- /dev/null +++ b/platform/winrt/gsview/Resources/zoom_in.ico diff --git a/platform/winrt/gsview/Resources/zoom_out.ico b/platform/winrt/gsview/Resources/zoom_out.ico Binary files differnew file mode 100644 index 00000000..a31d6c8b --- /dev/null +++ b/platform/winrt/gsview/Resources/zoom_out.ico diff --git a/platform/winrt/gsview/ghostsharp.cs b/platform/winrt/gsview/ghostsharp.cs new file mode 100644 index 00000000..50c08b57 --- /dev/null +++ b/platform/winrt/gsview/ghostsharp.cs @@ -0,0 +1,453 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks;using System.Runtime.InteropServices; +using System.IO; +using System.Security; +using System.ComponentModel; + +namespace gsview +{ + public enum gsDevice_t + { + bmp16, + bmp16m, + bmp256, + bmp32b, + bmpgray, + bmpmono, + epswrite, + jpeg, + jpegcmyk, + jpeggray, + pamcmyk32, + pamcmyk4, + pbm, + pgm, + png16, + png16m, + png256, + pngalpha, + pnggray, + pngmono, + pdfwrite, + ps2write, + psdcmyk, + psdrgb, + pxlcolor, + pxlmono, + tiff12nc, + tiff24nc, + tiff32nc, + tiff64nc, + tiffcrle, + tiffg3, + tiffg32d, + tiffg4, + tiffgray, + tifflzw, + tiffpack, + tiffsep, + txtwrite, + xpswrite + }; + + public enum GS_Task_t + { + PS_DISTILL, + CREATE_XPS, + SAVE_RESULT + } + + public enum GS_Result_t + { + gsOK, + gsFAILED + } + + /* Parameters */ + public struct gsParams_t + { + public int resolution; + public gsDevice_t device; + public String outputfile; + public String inputfile; + public GS_Task_t task; + public GS_Result_t result; + }; + + public class gsEventArgs : EventArgs + { + private bool m_completed; + private int m_progress; + private gsParams_t m_param; + + public bool Completed + { + get { return m_completed; } + } + + public gsParams_t Params + { + get { return m_param; } + } + + public int Progress + { + get { return m_progress; } + } + + public gsEventArgs(bool completed, int progress, gsParams_t param) + { + m_completed = completed; + m_progress = progress; + m_param = param; + } + } + + /* from gs */ + struct gsapi_revision_t + { + IntPtr product; + IntPtr copyright; + long revision; + long revisiondate; + } + + public enum gsEncoding { + GS_ARG_ENCODING_LOCAL = 0, + GS_ARG_ENCODING_UTF8 = 1, + GS_ARG_ENCODING_UTF16LE = 2 + }; + + public enum gsStatus + { + GS_READY, + GS_BUSY, + GS_ERROR + }; + + [SuppressUnmanagedCodeSecurity] + class ghostsharp + { + /* Callback proto for stdio */ + public delegate int gsStdIOHandler(IntPtr caller_handle, IntPtr buffer, + int len); + + /* Ghostscript API */ + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_revision(IntPtr stuct, int size); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_new_instance(out IntPtr pinstance, + IntPtr caller_handle); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern void gsapi_delete_instance(IntPtr instance); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_init_with_args(IntPtr instance, int argc, + IntPtr argv); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_exit(IntPtr instance); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_set_arg_encoding(IntPtr instance, + int encoding); + + [DllImport("gsdll64.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + public static extern int gsapi_set_stdio(IntPtr instance, + gsStdIOHandler stdin, gsStdIOHandler stdout, gsStdIOHandler stderr); + + private int StdInCallback(IntPtr handle, IntPtr pointer, int count) + { + String output = Marshal.PtrToStringAnsi(pointer); + return count; + } + + private int StdOutCallback(IntPtr handle, IntPtr pointer, int count) + { + String output = Marshal.PtrToStringAnsi(pointer); + gsIOUpdateMain(this, output, count); + return count; + } + + private int StdErrCallback(IntPtr handle, IntPtr pointer, int count) + { + String output = Marshal.PtrToStringAnsi(pointer); + gsIOUpdateMain(this, output, count); + return count; + } + + IntPtr gsInstance; + BackgroundWorker m_worker; + /* Callbacks to Main */ + internal delegate void gsIOCallBackMain(object gsObject, String mess, int len); + internal event gsIOCallBackMain gsIOUpdateMain; + internal delegate void gsCallBackMain(object gsObject, gsEventArgs info); + internal event gsCallBackMain gsUpdateMain; + + public ghostsharp() + { + m_worker = null; + gsInstance = IntPtr.Zero; + } + + /* A standard command line approach to using gs API */ + private void gsWork1(object sender, DoWorkEventArgs e) + { + gsParams_t Params = (gsParams_t) e.Argument; + String out_file = Params.outputfile; + String in_file = Params.inputfile; + int num_params = 9; + var argParam = new GCHandle[num_params]; + var argPtrs = new IntPtr[num_params]; + String[] strParams = new String[num_params]; + List<byte[]> CharacterArray = new List<byte[]>(num_params); + int e_Quit = -101; + GCHandle argPtrsStable; + + /* New instance */ + int code = gsapi_new_instance(out gsInstance, IntPtr.Zero); + if (code < 0) + { + Params.result = GS_Result_t.gsFAILED; + e.Result = Params; + return; + } + + var RaiseStdInCallback = new gsStdIOHandler(StdInCallback); + var RaiseStdOutCallback = new gsStdIOHandler(StdOutCallback); + var RaiseStdErrCallback = new gsStdIOHandler(StdErrCallback); + + var stdInPtr = Marshal.GetFunctionPointerForDelegate(RaiseStdInCallback); + var stdOutPtr = Marshal.GetFunctionPointerForDelegate(RaiseStdOutCallback); + var stdErrPtr = Marshal.GetFunctionPointerForDelegate(RaiseStdErrCallback); + + // Setup stdio callback functions + //code = gsapi_set_stdio(gsInstance, stdInPtr, stdOutPtr, stdErrPtr); + code = gsapi_set_stdio(gsInstance, RaiseStdInCallback, RaiseStdOutCallback, RaiseStdErrCallback); + + code = gsapi_set_arg_encoding(gsInstance, (int) gsEncoding.GS_ARG_ENCODING_UTF8); + if (code == 0) + { + strParams[0] = "gs"; /* This does not matter */ + strParams[1] = "-dNOPAUSE"; + strParams[2] = "-dBATCH"; + strParams[3] = "-dSAFER"; + strParams[4] = "-sDEVICE=" + Enum.GetName(typeof(gsDevice_t), Params.device); + strParams[5] = "-r" + Params.resolution; + /* Create temp file if file not specified */ + if (out_file == null) + { + out_file = Path.GetTempFileName(); + Params.outputfile = out_file; + } + strParams[6] = "-o" + out_file; + strParams[7] = "-f"; + strParams[8] = in_file; + + /* Now convert our Strings to char* and get pinned handles to these. + * This keeps the c# GC from moving stuff around on us */ + for (int k = 0; k < num_params; k++) + { + CharacterArray.Add(System.Text.Encoding.UTF8.GetBytes(strParams[k].ToCharArray())); + argParam[k] = GCHandle.Alloc(CharacterArray[k], GCHandleType.Pinned); + argPtrs[k] = argParam[k].AddrOfPinnedObject(); + } + /* Also stick the array of pointers into memory that will not be GCd */ + argPtrsStable = GCHandle.Alloc(argPtrs, GCHandleType.Pinned); + + code = gsapi_init_with_args(gsInstance, num_params, argPtrsStable.AddrOfPinnedObject()); + + /* All the pinned items need to be freed so the GC can do its job */ + for (int k = 0; k < num_params; k++) + { + argParam[k].Free(); + } + argPtrsStable.Free(); + } + + int code1 = gsapi_exit(gsInstance); + if ((code == 0) || (code == e_Quit)) + code = code1; + + RaiseStdInCallback = null; + RaiseStdOutCallback = null; + RaiseStdErrCallback = null; + + gsapi_delete_instance(gsInstance); + if ((code == 0) || (code == e_Quit)) + { + Params.result = GS_Result_t.gsOK; + e.Result = Params; + return; + } + + Params.result = GS_Result_t.gsFAILED; + e.Result = Params; + return; + } + + /* Feeding gs piecemeal so that we can have some progress callback */ + private void gsWork2(object sender, DoWorkEventArgs e) + { + gsParams_t Params = (gsParams_t)e.Argument; + String out_file = Params.outputfile; + String in_file = Params.inputfile; + int num_params = 10; + var argParam = new GCHandle[num_params]; + var argPtrs = new IntPtr[num_params]; + String[] strParams = new String[num_params]; + List<byte[]> CharacterArray = new List<byte[]>(num_params); + int e_Quit = -101; + GCHandle argPtrsStable; + + /* New instance */ + int code = gsapi_new_instance(out gsInstance, IntPtr.Zero); + if (code < 0) + { + Params.result = GS_Result_t.gsFAILED; + e.Result = Params; + return; + } + + code = gsapi_set_arg_encoding(gsInstance, (int)gsEncoding.GS_ARG_ENCODING_UTF8); + if (code == 0) + { + strParams[0] = "gs"; /* This does not matter */ + strParams[1] = "-dNOPAUSE"; + strParams[2] = "-dBATCH"; + strParams[3] = "-dSAFER"; + strParams[4] = "-sDEVICE=" + Enum.GetName(typeof(gsDevice_t), Params.device); + strParams[5] = "-r" + Params.resolution; + strParams[6] = "-sstdout=%sstderr"; /* Need to get setup to capture stdout and stderr */ + /* Create temp file if file not specified */ + if (out_file == null) + { + out_file = Path.GetTempFileName(); + Params.outputfile = out_file; + } + strParams[7] = "-sOutputFile=" + out_file; + strParams[8] = "-f"; + strParams[9] = in_file; + + /* Now convert our Strings to char* and get pinned handles to these. + * This keeps the c# GC from moving stuff around on us */ + for (int k = 0; k < num_params; k++) + { + CharacterArray.Add(System.Text.Encoding.UTF8.GetBytes(strParams[k].ToCharArray())); + argParam[k] = GCHandle.Alloc(CharacterArray[k], GCHandleType.Pinned); + argPtrs[k] = argParam[k].AddrOfPinnedObject(); + } + /* Also stick the array of pointers into memory that will not be GCd */ + argPtrsStable = GCHandle.Alloc(argPtrs, GCHandleType.Pinned); + + code = gsapi_init_with_args(gsInstance, num_params, argPtrsStable.AddrOfPinnedObject()); + + /* All the pinned items need to be freed so the GC can do its job */ + for (int k = 0; k < num_params; k++) + { + argParam[k].Free(); + } + argPtrsStable.Free(); + } + + int code1 = gsapi_exit(gsInstance); + if ((code == 0) || (code == e_Quit)) + code = code1; + + gsapi_delete_instance(gsInstance); + if ((code == 0) || (code == e_Quit)) + { + Params.result = GS_Result_t.gsOK; + e.Result = Params; + return; + } + + Params.result = GS_Result_t.gsFAILED; + e.Result = Params; + return; + } + + private void gsCompleted(object sender, RunWorkerCompletedEventArgs e) + { + /* Get the result and do the callback */ + gsParams_t Value = (gsParams_t)e.Result; + gsEventArgs info = new gsEventArgs(true, 100, Value); + gsUpdateMain(this, info); + } + + private void gsProgressChanged(object sender, ProgressChangedEventArgs e) + { + /* Get the result and do the callback */ + gsParams_t Value = new gsParams_t(); + gsEventArgs info = new gsEventArgs(false, e.ProgressPercentage, Value); + gsUpdateMain(this, info); + } + + public gsStatus DistillPS(String FileName) + { + gsParams_t Params = new gsParams_t(); ; + + Params.device = gsDevice_t.pdfwrite; + Params.outputfile = null; + Params.resolution = 300; + Params.inputfile = FileName; + Params.outputfile = null; + return RunGhostscript(Params); + } + + public gsStatus CreateXPS(String FileName) + { + gsParams_t Params = new gsParams_t(); ; + + Params.device = gsDevice_t.xpswrite; + Params.outputfile = null; + Params.resolution = 300; + Params.inputfile = FileName; + Params.outputfile = null; + return RunGhostscript(Params); + } + + private gsStatus RunGhostscript(gsParams_t Params) + { + /* Create background task for rendering the thumbnails. Allow + this to be cancelled if we open a new doc while we are in loop + rendering. Put the UI updates in the progress changed which will + run on the main thread */ + try + { + if (m_worker != null) + { + m_worker.CancelAsync(); + return gsStatus.GS_BUSY; + } + m_worker = new BackgroundWorker(); + m_worker.WorkerReportsProgress = true; + m_worker.WorkerSupportsCancellation = true; + m_worker.DoWork += new DoWorkEventHandler(gsWork1); + m_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(gsCompleted); + m_worker.ProgressChanged += new ProgressChangedEventHandler(gsProgressChanged); + m_worker.RunWorkerAsync(Params); + return gsStatus.GS_READY; + } + catch (OutOfMemoryException e) + { + Console.WriteLine("Memory allocation failed during gs rendering\n"); + return gsStatus.GS_ERROR; + } + } + + } +} diff --git a/platform/winrt/gsview/gsIO.cs b/platform/winrt/gsview/gsIO.cs new file mode 100644 index 00000000..831f34f7 --- /dev/null +++ b/platform/winrt/gsview/gsIO.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel; + +namespace gsview +{ + class gsIO : INotifyPropertyChanged + { + public String gsIOString + { + get; + set; + } + + public event PropertyChangedEventHandler PropertyChanged; + + public void PageRefresh() + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("gsIOString")); + } + } + + public gsIO() + { + this.gsIOString = ""; + } + } +} diff --git a/platform/winrt/gsview/gsOutput.xaml b/platform/winrt/gsview/gsOutput.xaml new file mode 100644 index 00000000..0be459a4 --- /dev/null +++ b/platform/winrt/gsview/gsOutput.xaml @@ -0,0 +1,35 @@ +<Window x:Class="gsview.gsOutput" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Title="Ghostscript Messages" Height="500" Width="500"> + + <DockPanel LastChildFill="True"> + <Grid DockPanel.Dock="Bottom" Visibility="Visible" Background="WhiteSmoke"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="Auto" /> + </Grid.ColumnDefinitions> + <Button Grid.Row="0" Grid.Column="2" Width="50" Height="20" Click="HideWindow" Background="Transparent" BorderBrush="Transparent" Margin="5,0,15,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>OK</Bold></TextBlock> + </Button> + </Grid> + + <!-- Pages are last child fill. This goes in the center of our dock panel --> + <Grid HorizontalAlignment="Stretch" Background="DarkGray"> + <TextBox x:Name="xaml_gsText" Margin="1, 1, 1, 1" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Text="{Binding gsIOString}" IsReadOnly="True"/> + </Grid> + + </DockPanel> +</Window> diff --git a/platform/winrt/gsview/gsOutput.xaml.cs b/platform/winrt/gsview/gsOutput.xaml.cs new file mode 100644 index 00000000..90bb2d55 --- /dev/null +++ b/platform/winrt/gsview/gsOutput.xaml.cs @@ -0,0 +1,54 @@ +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; + +namespace gsview +{ + /// <summary> + /// Interaction logic for gsOutput.xaml + /// </summary> + public partial class gsOutput : Window + { + gsIO m_gsIO; + public gsOutput() + { + InitializeComponent(); + this.Closing += new System.ComponentModel.CancelEventHandler(FakeWindowClosing); + m_gsIO = new gsIO(); + xaml_gsText.DataContext = m_gsIO; + } + + void FakeWindowClosing(object sender, System.ComponentModel.CancelEventArgs e) + { + e.Cancel = true; + this.Hide(); + } + + private void HideWindow(object sender, RoutedEventArgs e) + { + this.Hide(); + } + + public void RealWindowClosing() + { + this.Closing -= new System.ComponentModel.CancelEventHandler(FakeWindowClosing); + this.Close(); + } + + public void Update(String newstring, int len) + { + m_gsIO.gsIOString += newstring.Substring(0, len); + m_gsIO.PageRefresh(); + } + } +} diff --git a/platform/winrt/gsview/gsprint.cs b/platform/winrt/gsview/gsprint.cs new file mode 100644 index 00000000..8fb7ad81 --- /dev/null +++ b/platform/winrt/gsview/gsprint.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Packaging; +using System.Printing; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Documents.Serialization; +using System.Windows.Media; +using System.Windows.Xps; +using System.Windows.Xps.Packaging; +using System.Windows.Xps.Serialization; + +namespace gsview +{ + /* Class for handling async print progress callback */ + public class gsPrintEventArgs : EventArgs + { + private String m_status; + private bool m_completed; + private int m_page; + + public String Status + { + get { return m_status; } + } + + public bool Completed + { + get { return m_completed; } + } + + public int Page + { + get { return m_page; } + } + + public gsPrintEventArgs(String status, bool completed, int page) + { + m_completed = completed; + m_status = status; + m_page = page; + } + } + + public class gsprint + { + private XpsDocumentWriter m_docWriter = null; + internal delegate void AsyncPrintCallBack(object printObject, gsPrintEventArgs info); + internal event AsyncPrintCallBack PrintUpdate; + + /* Show std. print dialog */ + public PrintDialog GetPrintDialog() + { + PrintDialog dlg = new PrintDialog(); + /* Current page and page ranges is going to require a little work */ + dlg.PageRangeSelection = PageRangeSelection.AllPages; + //dlg.UserPageRangeEnabled = true; + //dlg.CurrentPageEnabled = true; + dlg.SelectedPagesEnabled = false; + if (dlg.ShowDialog() == true) + return dlg; + return null; + } + + /* Main print entry point */ + public void Print(PrintQueue queu, FixedDocumentSequence fixdoc) + { + XpsDocumentWriter docwrite = GetDocWriter(queu); + + docwrite.WritingPrintTicketRequired += + new WritingPrintTicketRequiredEventHandler(PrintTicket); + PrintPages(docwrite, fixdoc); + } + + /* Send it */ + private void PrintPages(XpsDocumentWriter xpsdw, FixedDocumentSequence fixdoc) + { + m_docWriter = xpsdw; + xpsdw.WritingCompleted += + new WritingCompletedEventHandler(AsyncCompleted); + xpsdw.WritingProgressChanged += + new WritingProgressChangedEventHandler(AsyncProgress); + xpsdw.WriteAsync(fixdoc); + } + + public void CancelAsync() + { + /* ick. This does not work in windows 8. causes crash */ + /* https://connect.microsoft.com/VisualStudio/feedback/details/778145/xpsdocumentwriter-cancelasync-cause-crash-in-win8 */ + m_docWriter.CancelAsync(); + } + + /* Done */ + private void AsyncCompleted(object sender, WritingCompletedEventArgs e) + { + string status = null; + if (e.Cancelled) + status = "Print Canceled"; + else if (e.Error != null) + status = "Print Error"; + else + status = "Print Completed"; + + if (PrintUpdate != null) + { + gsPrintEventArgs info = new gsPrintEventArgs(status, true, 0); + PrintUpdate(this, info); + } + } + + /* Do this update with each fixed document (page) that is handled */ + private void AsyncProgress(object sender, WritingProgressChangedEventArgs e) + { + if (PrintUpdate != null) + { + String progress = "Page " + e.Number; + gsPrintEventArgs info = new gsPrintEventArgs(progress, false, e.Number); + PrintUpdate(this, info); + } + } + + /* Print ticket handling. You can customize for PrintTicketLevel at + FixedDocumentSequencePrintTicket, FixedDocumentPrintTicket, + or FixedPagePrintTicket. We may want to play around with this some */ + private void PrintTicket(Object sender, WritingPrintTicketRequiredEventArgs e) + { + if (e.CurrentPrintTicketLevel == + PrintTicketLevel.FixedDocumentSequencePrintTicket) + { + PrintTicket pts = new PrintTicket(); + pts.PageOrientation = PageOrientation.Portrait; + e.CurrentPrintTicket = pts; + } + } + + /* Create the document write */ + private XpsDocumentWriter GetDocWriter(PrintQueue pq) + { + XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq); + return xpsdw; + } + } +} diff --git a/platform/winrt/gsview/gsview.csproj b/platform/winrt/gsview/gsview.csproj index 961eab19..6856e925 100644 --- a/platform/winrt/gsview/gsview.csproj +++ b/platform/winrt/gsview/gsview.csproj @@ -13,6 +13,7 @@ <FileAlignment>512</FileAlignment> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <WarningLevel>4</WarningLevel> + <IsWebBootstrapper>false</IsWebBootstrapper> <PublishUrl>publish\</PublishUrl> <Install>true</Install> <InstallFrom>Disk</InstallFrom> @@ -25,12 +26,11 @@ <MapFileExtensions>true</MapFileExtensions> <ApplicationRevision>0</ApplicationRevision> <ApplicationVersion>1.0.0.%2a</ApplicationVersion> - <IsWebBootstrapper>false</IsWebBootstrapper> <UseApplicationTrust>false</UseApplicationTrust> <BootstrapperEnabled>true</BootstrapperEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> + <PlatformTarget>x64</PlatformTarget> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> @@ -38,9 +38,11 @@ <DefineConstants>TRACE;DEBUG</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PlatformTarget>AnyCPU</PlatformTarget> + <PlatformTarget>x64</PlatformTarget> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> @@ -48,19 +50,25 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> + <PropertyGroup> + <StartupObject /> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>gsview.ico</ApplicationIcon> + </PropertyGroup> <ItemGroup> + <Reference Include="ReachFramework" /> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Drawing" /> + <Reference Include="System.Printing" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Xml" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Core" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Xaml"> <RequiredTargetFramework>4.0</RequiredTargetFramework> </Reference> + <Reference Include="UIAutomationProvider" /> + <Reference Include="UIAutomationTypes" /> <Reference Include="WindowsBase" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> @@ -71,8 +79,28 @@ <SubType>Designer</SubType> </ApplicationDefinition> <Compile Include="ContentEntry.cs" /> + <Compile Include="ContentItem.cs" /> + <Compile Include="Convert.xaml.cs"> + <DependentUpon>Convert.xaml</DependentUpon> + </Compile> <Compile Include="DocPage.cs" /> + <Compile Include="ghostsharp.cs" /> + <Compile Include="gsIO.cs" /> + <Compile Include="gsOutput.xaml.cs"> + <DependentUpon>gsOutput.xaml</DependentUpon> + </Compile> + <Compile Include="gsprint.cs" /> + <Compile Include="Links.cs" /> + <Compile Include="mudocument.cs" /> <Compile Include="RectList.cs" /> + <Page Include="Convert.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="gsOutput.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="MainWindow.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -138,6 +166,31 @@ <Install>false</Install> </BootstrapperPackage> </ItemGroup> + <ItemGroup> + <Resource Include="Resources\Left.ico" /> + <Resource Include="Resources\Right.ico" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\thumbnail.ico" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\hyperlink.png" /> + <Resource Include="Resources\search.ico" /> + <Resource Include="Resources\zoom_in.ico" /> + <Resource Include="Resources\zoom_out.ico" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\search.png" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\contents.ico" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Resources\gsview.ico" /> + </ItemGroup> + <ItemGroup> + <Resource Include="gsview.ico" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/platform/winrt/gsview/gsview.ico b/platform/winrt/gsview/gsview.ico Binary files differnew file mode 100644 index 00000000..65b8b6b9 --- /dev/null +++ b/platform/winrt/gsview/gsview.ico diff --git a/platform/winrt/gsview/mudocument.cs b/platform/winrt/gsview/mudocument.cs new file mode 100644 index 00000000..c9ccb4de --- /dev/null +++ b/platform/winrt/gsview/mudocument.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Threading; +using System.Runtime.InteropServices; +using System.Security; +using System.Windows; + +/* This file contains the interface between the muctx cpp class, which + implements the mupdf calls and the .net managed code */ + +namespace gsview +{ + + public struct content_s + { + public int page; + public IntPtr string_margin; + } + + [SuppressUnmanagedCodeSecurity] + class mudocument + { + IntPtr mu_object; + private System.Object m_lock = new System.Object(); + List<Links> links; + List<Links> textsearch; + public List<ContentItem> contents; + + /* The list of functions that we use to call into C interface of muctx. + * Calling into C++ code from managed code is complex. Since CLR + * compiling is needed and that does not support mutex. Hence the C + * interface */ + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern IntPtr mInitialize(); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern status_t mOpenDocument(IntPtr ctx, string filename); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern void mCleanUp(IntPtr ctx); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern int mGetPageCount(IntPtr ctx); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern bool mRequiresPassword(IntPtr ctx); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern bool mApplyPassword(IntPtr ctx, string password); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern int mRenderPage(IntPtr ctx, + int page_num, Byte[] bmp_data, int bmp_width, + int bmp_height, double scale, bool flipy); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern int mMeasurePage(IntPtr ctx, int page_num, + ref double width, ref double height); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern int mGetContents(IntPtr ctx); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern void mReleaseContents(); + + /* The managed code Marshal actually releases the allocated string from C */ + [DllImport("munet.dll", CharSet = CharSet.Ansi, + CallingConvention = CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static extern string mGetContentsItem(int k, ref int len, ref int page); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern IntPtr mCreateDisplayList(IntPtr ctx, int page_num, + ref int page_width, ref int page_height); + + [DllImport("munet.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern int mRenderPageMT(IntPtr ctx, IntPtr dlist, + int page_width, int page_height, Byte[] bmp_data, int bmp_width, + int bmp_height, double scale, bool flipy); + +/* + [DllImport("mugs.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern void GetLinks(IntPtr ctx); + + [DllImport("mugs.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern void GetTextSearch(IntPtr ctx); + + [DllImport("mugs.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + public static extern void GetHTML(IntPtr ctx); + + ~muctx(void); + + unsigned int GetLinks(int page_num, sh_vector_link links_vec); + int GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec); + std::string GetHTML(int page_num); +*/ + + public status_t Initialize() + { + mu_object = mInitialize(); + if (mu_object == null) + { + return status_t.E_FAILURE; + } + else + { + return status_t.S_ISOK; + } + } + + public void CleanUp() + { + if (mu_object != null) + mCleanUp(mu_object); + } + + public int GetPageCount() + { + return mGetPageCount(mu_object); + } + + public bool RequiresPassword() + { + return mRequiresPassword(mu_object); + } + + public bool ApplyPassword(String password) + { + return mApplyPassword(mu_object, password); + } + + public int RenderPage(int page_num, Byte[] bmp_data, int bmp_width, + int bmp_height, double scale, bool flipy, bool use_dlist) + { + int code; + + if (use_dlist) + { + IntPtr dlist; + int page_height = 0; + int page_width = 0; + + lock(m_lock) + { + dlist = mCreateDisplayList(mu_object, page_num, ref page_width, ref page_height); + } + /* Rendering of display list can occur with other threads so unlock */ + if (dlist == null) + { + return (int) status_t.E_FAILURE; + } + code = mRenderPageMT(mu_object, dlist, page_width, page_height, + bmp_data, bmp_width, bmp_height, + scale, flipy); + } + else + { + lock(m_lock) + { + code = mRenderPage(mu_object, page_num, bmp_data, bmp_width, + bmp_height, scale, flipy); + } + } + return code; + } + + public status_t OpenFile(string filename) + { + return mOpenDocument(mu_object, filename); + } + + public int GetPageSize(int page_num, out Point size_out) + { + int code; + double height = 0, width = 0; + + size_out = new Point(); + + lock(m_lock) + { + code = mMeasurePage(mu_object, page_num, ref width, ref height); + } + + size_out.X = width; + size_out.Y = height; + return code; + } + + public int ComputeContents() + { + int num_items; + int len = 0, page = 0; + + lock(m_lock) + { + num_items = mGetContents(mu_object); + } + + if (contents == null) + contents = new List<ContentItem>(); + + for (int k = 0; k < num_items; k++) + { + ContentItem item = new ContentItem(); + item.StringMargin = mGetContentsItem(k, ref len, ref page); + item.Page = page; + contents.Add(item); + } + return num_items; + } + + public void ReleaseContents() + { + mReleaseContents(); + } + } +} |