using System; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Runtime.InteropServices; using System.Windows.Controls; using GhostNET; namespace ghostnet_wpf_example { public partial class MainWindow { /* Filter so we get the first non-full res and the last * full res */ private void PageRangeRender(int first_page, int last_page) { if (m_viewer_state != ViewerState_t.DOC_OPEN) return; int real_first_page = -1; int real_last_page = -1; for (int k = first_page; k <= last_page; k++) { if (real_first_page == -1 && ((m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION) || (m_docPages[k].AA != m_aa))) { real_first_page = k; } if (m_docPages[k].Content != Page_Content_t.FULL_RESOLUTION || m_docPages[k].AA != m_aa) { real_last_page = k; } } if (real_first_page == -1) return; m_viewer_state = ViewerState_t.BUSY_RENDER; m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, real_first_page + 1, real_last_page + 1); } /* Callback from ghostscript with the rendered image. */ private void MainPageCallback(int width, int height, int raster, double zoom_in, int page_num, IntPtr data) { Byte[] bitmap = new byte[raster * height]; idata_t image_data = new idata_t(); Marshal.Copy(data, bitmap, 0, raster * height); image_data.bitmap = bitmap; image_data.page_num = page_num; image_data.width = width; image_data.height = height; image_data.raster = raster; image_data.zoom = zoom_in; m_images_rendered.Add(image_data); /* Dispatch progress bar update on UI thread */ System.Windows.Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send, new Action(() => { m_page_progress_count += 1; xaml_RenderProgress.Value = ((double)m_page_progress_count / (double) m_numpages) * 100.0; })); } /* Done rendering. Update the pages with the new raster information if needed */ private void RenderingDone() { for (int k = 0; k < m_images_rendered.Count; k++) { DocPage doc_page = m_docPages[m_images_rendered[k].page_num - 1]; if (doc_page.Content != Page_Content_t.FULL_RESOLUTION || doc_page.AA != m_aa) { doc_page.Width = m_images_rendered[k].width; doc_page.Height = m_images_rendered[k].height; doc_page.Content = Page_Content_t.FULL_RESOLUTION; doc_page.Zoom = m_doczoom; doc_page.AA = m_aa; doc_page.BitMap = BitmapSource.Create(doc_page.Width, doc_page.Height, 72, 72, PixelFormats.Bgr24, BitmapPalettes.Halftone256, m_images_rendered[k].bitmap, m_images_rendered[k].raster); } } xaml_ProgressGrid.Visibility = System.Windows.Visibility.Collapsed; xaml_RenderProgress.Value = 0; m_images_rendered.Clear(); m_viewer_state = ViewerState_t.DOC_OPEN; } private Tuple GetVisiblePages() { /* First child of list view */ Decorator border = VisualTreeHelper.GetChild(xaml_PageList, 0) as Decorator; // Get scrollviewer ScrollViewer scrollViewer = border.Child as ScrollViewer; double top_window = scrollViewer.VerticalOffset; double bottom_window = top_window + scrollViewer.ViewportHeight; int first_page = -1; int last_page = -1; if (top_window > m_toppage_pos[m_numpages - 1]) { first_page = m_numpages - 1; last_page = first_page; } else { for (int k = 0; k < (m_toppage_pos.Count - 1); k++) { if (top_window <= m_toppage_pos[k + 1] && bottom_window >= m_toppage_pos[k]) { if (first_page == -1) { first_page = k; last_page = k; } else { last_page = k; break; } } else { if (first_page != -1) { last_page = first_page; break; } } } } return new Tuple(first_page, last_page); } /* Render only visible pages. Used for single page formats as well * as PDF (and ideally XPS) where the interpreter can interpret only * specified pages */ private void RenderMainRange() { if (m_viewer_state == ViewerState_t.OPENING) { m_doczoom = 1.0; xaml_Zoomsize.Text = "100"; m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered); } m_viewer_state = ViewerState_t.BUSY_RENDER; (int first_page, int last_page) = GetVisiblePages(); m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, first_page + 1, last_page + 1); } /* Render all pages full resolution. Used for single page files as * well as documents like PostScript and PCL that are not page * based indexed */ private void RenderMainAll() { xaml_RenderProgress.Value = 0; xaml_ProgressGrid.Visibility = System.Windows.Visibility.Visible; m_page_progress_count = 0; xaml_RenderProgressText.Text = "Rendering"; if (m_viewer_state == ViewerState_t.OPENING) { m_doczoom = 1.0; xaml_Zoomsize.Text = "100"; m_ghostscript.gsPageRenderedMain += new ghostsharp.gsCallBackPageRenderedMain(gsPageRendered); } m_viewer_state = ViewerState_t.BUSY_RENDER; m_ghostscript.gsDisplayDeviceRunFile(m_currfile, m_doczoom, m_aa, -1, -1); } /* Called via zoom or aa changes */ private void RenderMain() { if (m_viewer_state != ViewerState_t.DOC_OPEN) return; if (m_doc_type_has_page_access) RenderMainRange(); else RenderMainAll(); } } }