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; using System.ComponentModel; using System.Windows.Forms; /* This file contains the interface between the muctx cpp class, which implements the mupdf calls and the .net managed code */ namespace gsview { /* Parameters for conversion */ public struct ConvertParams_t { public int resolution; public gsDevice_t device; public String outputfile; public int num_pages; public System.Collections.IList pages; public int currpage; public GS_Result_t result; }; /* Must match enum in muctx.h */ enum mudevice_t { SVG_OUT, PNM_OUT, PCL_OUT, PWG_OUT, }; public class muPDFEventArgs : EventArgs { private bool m_completed; private int m_progress; private ConvertParams_t m_param; public bool Completed { get { return m_completed; } } public ConvertParams_t Params { get { return m_param; } } public int Progress { get { return m_progress; } } public muPDFEventArgs(bool completed, int progress, ConvertParams_t param) { m_completed = completed; m_progress = progress; m_param = param; } } public struct content_s { public int page; public IntPtr string_margin; } [SuppressUnmanagedCodeSecurity] class mudocument { public bool is64bit; IntPtr mu_object; BackgroundWorker m_worker; ConvertParams_t m_params; /* Callbacks to Main */ internal delegate void mupdfDLLProblem(object muObject, String mess); internal event mupdfDLLProblem mupdfDLLProblemMain; internal delegate void mupdfCallBackMain(object muObject, muPDFEventArgs info); internal event mupdfCallBackMain mupdfUpdateMain; private System.Object m_lock = new System.Object(); public List contents; #region DLLInterface /* 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("mupdfnet64.dll", EntryPoint = "mInitialize", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mInitialize64(); [DllImport("mupdfnet64.dll", EntryPoint = "mOpenDocument", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern status_t mOpenDocument64(IntPtr ctx, string filename); [DllImport("mupdfnet64.dll", EntryPoint = "mCleanUp", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mCleanUp64(IntPtr ctx); [DllImport("mupdfnet64.dll", EntryPoint = "mGetPageCount", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetPageCount64(IntPtr ctx); [DllImport("mupdfnet64.dll", EntryPoint = "mRequiresPassword", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mRequiresPassword64(IntPtr ctx); [DllImport("mupdfnet64.dll", EntryPoint = "mApplyPassword", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mApplyPassword64(IntPtr ctx, string password); [DllImport("mupdfnet64.dll", EntryPoint = "mRenderPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mRenderPage64(IntPtr ctx, int page_num, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy); [DllImport("mupdfnet64.dll", EntryPoint = "mMeasurePage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mMeasurePage64(IntPtr ctx, int page_num, ref double width, ref double height); [DllImport("mupdfnet64.dll", EntryPoint = "mGetContents", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetContents64(IntPtr ctx); [DllImport("mupdfnet64.dll", EntryPoint = "mReleaseContents", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseContents64(); [DllImport("mupdfnet64.dll", EntryPoint = "mSetAA", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mSetAA64(IntPtr ctx, int level); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet64.dll", EntryPoint = "mGetContentsItem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetContentsItem64(int k, ref int len, ref int page); [DllImport("mupdfnet64.dll", EntryPoint = "mCreateDisplayList", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayList64(IntPtr ctx, int page_num, ref int page_width, ref int page_height); [DllImport("mupdfnet64.dll", EntryPoint = "mCreateDisplayListAnnot", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayListAnnot64(IntPtr ctx, int page_num); [DllImport("mupdfnet64.dll", EntryPoint = "mCreateDisplayListText", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayListText64(IntPtr ctx, int page_num, ref int page_width, ref int page_height, ref IntPtr text, ref int length); [DllImport("mupdfnet64.dll", EntryPoint = "mRenderPageMT", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mRenderPageMT64(IntPtr ctx, IntPtr dlist, IntPtr annot_dlist, int page_width, int page_height, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy); [DllImport("mupdfnet64.dll", EntryPoint = "mTextSearchPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mTextSearchPage64(IntPtr ctx, int page_num, string needle); [DllImport("mupdfnet64.dll", EntryPoint = "mGetTextSearchItem", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mGetTextSearchItem64(int item_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet64.dll", EntryPoint = "mReleaseTextSearch", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseTextSearch64(); [DllImport("mupdfnet64.dll", EntryPoint = "mGetLinksPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetLinksPage64(IntPtr ctx, int page_num); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet64.dll", EntryPoint = "mGetLinkItem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetLinkItem64(int item_num, ref double top_x, ref double top_y, ref double height, ref double width, ref int topage, ref int type); [DllImport("mupdfnet64.dll", EntryPoint = "mReleaseLink", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseLink64(); [DllImport("mupdfnet64.dll", EntryPoint = "mReleaseText", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseText64(IntPtr ctx, IntPtr textpage); [DllImport("mupdfnet64.dll", EntryPoint = "mGetTextBlock", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextBlock64(IntPtr textpage, int block_num, ref double top_x,ref double top_y, ref double height, ref double width); [DllImport("mupdfnet64.dll", EntryPoint = "mGetTextLine", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextLine64(IntPtr textpage, int block_num, int line_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet64.dll", EntryPoint = "mGetTextCharacter", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextCharacter64(IntPtr textpage, int block_num, int line_num, int item_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet64.dll", EntryPoint = "mExtractPages", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mExtractPages64(String infile, String outfile, String password, bool has_password, bool linearize, int num_pages, IntPtr pages); [DllImport("mupdfnet64.dll", EntryPoint = "mSavePage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mSavePage64(IntPtr ctx, String outfile, int page_num, int res, int type, bool append); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet64.dll", EntryPoint = "mGetVers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetVers64(); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet64.dll", EntryPoint = "mGetText", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetText64(IntPtr ctx, int pagenum, int type); /* And the 32bit version */ [DllImport("mupdfnet32.dll", EntryPoint = "mInitialize", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mInitialize32(); [DllImport("mupdfnet32.dll", EntryPoint = "mOpenDocument", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern status_t mOpenDocument32(IntPtr ctx, string filename); [DllImport("mupdfnet32.dll", EntryPoint = "mCleanUp", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mCleanUp32(IntPtr ctx); [DllImport("mupdfnet32.dll", EntryPoint = "mGetPageCount", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetPageCount32(IntPtr ctx); [DllImport("mupdfnet32.dll", EntryPoint = "mRequiresPassword", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mRequiresPassword32(IntPtr ctx); [DllImport("mupdfnet32.dll", EntryPoint = "mApplyPassword", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mApplyPassword32(IntPtr ctx, string password); [DllImport("mupdfnet32.dll", EntryPoint = "mRenderPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mRenderPage32(IntPtr ctx, int page_num, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy); [DllImport("mupdfnet32.dll", EntryPoint = "mMeasurePage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mMeasurePage32(IntPtr ctx, int page_num, ref double width, ref double height); [DllImport("mupdfnet32.dll", EntryPoint = "mGetContents", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetContents32(IntPtr ctx); [DllImport("mupdfnet32.dll", EntryPoint = "mReleaseContents", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseContents32(); [DllImport("mupdfnet32.dll", EntryPoint = "mSetAA", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mSetAA32(IntPtr ctx, int level); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet32.dll", EntryPoint = "mGetContentsItem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetContentsItem32(int k, ref int len, ref int page); [DllImport("mupdfnet32.dll", EntryPoint = "mCreateDisplayList", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayList32(IntPtr ctx, int page_num, ref int page_width, ref int page_height); [DllImport("mupdfnet32.dll", EntryPoint = "mCreateDisplayListAnnot", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayListAnnot32(IntPtr ctx, int page_num); [DllImport("mupdfnet32.dll", EntryPoint = "mCreateDisplayListText", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr mCreateDisplayListText32(IntPtr ctx, int page_num, ref int page_width, ref int page_height, ref IntPtr text, ref int length); [DllImport("mupdfnet32.dll", EntryPoint = "mRenderPageMT", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mRenderPageMT32(IntPtr ctx, IntPtr dlist, IntPtr annot_dlist, int page_width, int page_height, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy); [DllImport("mupdfnet32.dll", EntryPoint = "mTextSearchPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mTextSearchPage32(IntPtr ctx, int page_num, string needle); [DllImport("mupdfnet32.dll", EntryPoint = "mGetTextSearchItem", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern bool mGetTextSearchItem32(int item_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet32.dll", EntryPoint = "mReleaseTextSearch", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseTextSearch32(); [DllImport("mupdfnet32.dll", EntryPoint = "mGetLinksPage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetLinksPage32(IntPtr ctx, int page_num); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet32.dll", EntryPoint = "mGetLinkItem", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetLinkItem32(int item_num, ref double top_x, ref double top_y, ref double height, ref double width, ref int topage, ref int type); [DllImport("mupdfnet32.dll", EntryPoint = "mReleaseLink", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseLink32(); [DllImport("mupdfnet32.dll", EntryPoint = "mReleaseText", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern void mReleaseText32(IntPtr ctx, IntPtr textpage); [DllImport("mupdfnet32.dll", EntryPoint = "mGetTextBlock", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextBlock32(IntPtr textpage, int block_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet32.dll", EntryPoint = "mGetTextLine", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextLine32(IntPtr textpage, int block_num, int line_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet32.dll", EntryPoint = "mGetTextCharacter", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mGetTextCharacter32(IntPtr textpage, int block_num, int line_num, int item_num, ref double top_x, ref double top_y, ref double height, ref double width); [DllImport("mupdfnet32.dll", EntryPoint = "mExtractPages", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mExtractPages32(String infile, String outfile, String password, bool has_password, bool linearize, int num_pages, IntPtr pages); [DllImport("mupdfnet32.dll", EntryPoint = "mSavePage", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern int mSavePage32(IntPtr ctx, String outfile, int page_num, int res, int type, bool append); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet32.dll", EntryPoint = "mGetVers", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetVers32(); /* The managed code Marshal actually releases the allocated string from C */ [DllImport("mupdfnet32.dll", EntryPoint = "mGetText", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.LPStr)] private static extern string mGetText32(IntPtr ctx, int pagenum, int type); #endregion DLLInterface #region DLLErrorTrap /* And make sure we can catch any issues in finding the DLL or if we have * a 32bit 64bit issue */ private IntPtr tc_mInitialize() { IntPtr output; try { if (is64bit) output = mInitialize64(); else output = mInitialize32(); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 1"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } return output; } private status_t tc_mOpenDocument(IntPtr ctx, string filename) { status_t output; try { if (is64bit) output = mOpenDocument64(ctx, filename); else output = mOpenDocument32(ctx, filename); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 2"; mupdfDLLProblemMain(this, err); return status_t.E_FAILURE; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return status_t.E_FAILURE; } return output; } private int tc_mCleanUp(IntPtr ctx) { try { if (is64bit) mCleanUp64(ctx); else mCleanUp32(ctx); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 3"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private int tc_mGetPageCount(IntPtr ctx) { int output; try { if (is64bit) output = mGetPageCount64(ctx); else output = mGetPageCount32(ctx); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 4"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private bool tc_mRequiresPassword(IntPtr ctx) { bool output; try { if (is64bit) output = mRequiresPassword64(ctx); else output = mRequiresPassword32(ctx); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 5"; mupdfDLLProblemMain(this, err); return false; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return false; } return output; } private bool tc_mApplyPassword(IntPtr ctx, string password) { bool output; try { if (is64bit) output = mApplyPassword64(ctx, password); else output = mApplyPassword32(ctx, password); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 6"; mupdfDLLProblemMain(this, err); return false; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return false; } return output; } private int tc_mRenderPage(IntPtr ctx, int page_num, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy) { int output; try { if (is64bit) output = mRenderPage64(ctx, page_num, bmp_data, bmp_width, bmp_height, scale, flipy); else output = mRenderPage32(ctx, page_num, bmp_data, bmp_width, bmp_height, scale, flipy); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 7"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mMeasurePage(IntPtr ctx, int page_num, ref double width, ref double height) { int output; try { if (is64bit) output = mMeasurePage64(ctx, page_num, ref width, ref height); else output = mMeasurePage32(ctx, page_num, ref width, ref height); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 8"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mGetContents(IntPtr ctx) { int output; try { if (is64bit) output = mGetContents64(ctx); else output = mGetContents32(ctx); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 9"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mReleaseContents() { try { if (is64bit) mReleaseContents64(); else mReleaseContents32(); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 10"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private string tc_mGetContentsItem(int k, ref int len, ref int page) { String output; try { if (is64bit) output = mGetContentsItem64(k, ref len, ref page); else output = mGetContentsItem32(k, ref len, ref page); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 11"; mupdfDLLProblemMain(this, err); return null; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return null; } return output; } private IntPtr tc_mCreateDisplayListAnnot(IntPtr ctx, int page_num) { IntPtr output; try { if (is64bit) output = mCreateDisplayListAnnot64(ctx, page_num); else output = mCreateDisplayListAnnot32(ctx, page_num); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 12"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } return output; } private IntPtr tc_mCreateDisplayList(IntPtr ctx, int page_num, ref int page_width, ref int page_height) { IntPtr output; try { if (is64bit) output = mCreateDisplayList64(ctx, page_num, ref page_width, ref page_height); else output = mCreateDisplayList32(ctx, page_num, ref page_width, ref page_height); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 13"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } return output; } private int tc_mSetAA(IntPtr ctx, int level) { try { if (is64bit) mSetAA64(ctx, level); else mSetAA32(ctx, level); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 14"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private IntPtr tc_mCreateDisplayListText(IntPtr ctx, int page_num, ref int page_width, ref int page_height, ref IntPtr text, ref int length) { IntPtr output; try { if (is64bit) output = mCreateDisplayListText64(ctx, page_num, ref page_width, ref page_height, ref text, ref length); else output = mCreateDisplayListText32(ctx, page_num, ref page_width, ref page_height, ref text, ref length); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 15"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return IntPtr.Zero; } return output; } private int tc_mRenderPageMT(IntPtr ctx, IntPtr dlist, IntPtr annot_dlist, int page_width, int page_height, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy) { int output; try { if (is64bit) output = mRenderPageMT64(ctx, dlist, annot_dlist, page_width, page_height, bmp_data, bmp_width, bmp_height, scale, flipy); else output = mRenderPageMT32(ctx, dlist, annot_dlist, page_width, page_height, bmp_data, bmp_width, bmp_height, scale, flipy); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 16"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mTextSearchPage(IntPtr ctx, int page_num, string needle) { int output; try { if (is64bit) output = mTextSearchPage64(ctx, page_num, needle); else output = mTextSearchPage32(ctx, page_num, needle); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 17"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private bool tc_mGetTextSearchItem(int item_num, ref double top_x, ref double top_y, ref double height, ref double width) { bool output; try { if (is64bit) output = mGetTextSearchItem64(item_num, ref top_x, ref top_y, ref height, ref width); else output = mGetTextSearchItem32(item_num, ref top_x, ref top_y, ref height, ref width); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 18"; mupdfDLLProblemMain(this, err); return false; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return false; } return output; } private int tc_mReleaseTextSearch() { try { if (is64bit) mReleaseTextSearch64(); else mReleaseTextSearch32(); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 18"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private int tc_mGetLinksPage(IntPtr ctx, int page_num) { int output; try { if (is64bit) output = mGetLinksPage64(ctx, page_num); else output = mGetLinksPage32(ctx, page_num); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 19"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private string tc_mGetLinkItem(int item_num, ref double top_x, ref double top_y, ref double height, ref double width, ref int topage, ref int type) { String output; try { if (is64bit) output = mGetLinkItem64(item_num, ref top_x, ref top_y, ref height, ref width, ref topage, ref type); else output = mGetLinkItem32(item_num, ref top_x, ref top_y, ref height, ref width, ref topage, ref type); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 20"; mupdfDLLProblemMain(this, err); return null; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return null; } return output; } private int tc_mReleaseLink() { try { if (is64bit) mReleaseLink64(); else mReleaseLink32(); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 21"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private int tc_mReleaseText(IntPtr ctx, IntPtr textpage) { try { if (is64bit) mReleaseText64(ctx, textpage); else mReleaseText32(ctx, textpage); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 22"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return 0; } private int tc_mGetTextBlock(IntPtr textpage, int block_num, ref double top_x, ref double top_y, ref double height, ref double width) { int output; try { if (is64bit) output = mGetTextBlock64(textpage, block_num, ref top_x, ref top_y, ref height, ref width); else output = mGetTextBlock32(textpage, block_num, ref top_x, ref top_y, ref height, ref width); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 23"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mGetTextLine(IntPtr textpage, int block_num, int line_num, ref double top_x, ref double top_y, ref double height, ref double width) { int output; try { if (is64bit) output = mGetTextLine64(textpage, block_num, line_num, ref top_x, ref top_y, ref height, ref width); else output = mGetTextLine32(textpage, block_num, line_num, ref top_x, ref top_y, ref height, ref width); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 24"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mGetTextCharacter(IntPtr textpage, int block_num, int line_num, int item_num, ref double top_x, ref double top_y, ref double height, ref double width) { int output; try { if (is64bit) output = mGetTextCharacter64(textpage, block_num, line_num, item_num, ref top_x, ref top_y, ref height, ref width); else output = mGetTextCharacter32(textpage, block_num, line_num, item_num, ref top_x, ref top_y, ref height, ref width); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 25"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private int tc_mExtractPages(String infile, String outfile, String password, bool has_password, bool linearize, int num_pages, IntPtr pages) { int output; try { if (is64bit) output = mExtractPages64(infile, outfile, password, has_password, linearize, num_pages, pages); else output = mExtractPages32(infile, outfile, password, has_password, linearize, num_pages, pages); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 26"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } private string tc_mGetVers() { String output; try { if (is64bit) output = mGetVers64(); else output = mGetVers32(); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 27"; mupdfDLLProblemMain(this, err); return null; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return null; } return output; } private string tc_mGetText(IntPtr ctx, int pagenum, textout_t type) { String output; try { if (is64bit) output = mGetText64(ctx, pagenum, (int) type); else output = mGetText32(ctx, pagenum, (int) type); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 28"; mupdfDLLProblemMain(this, err); return null; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return null; } return output; } private int tc_mSavePage(IntPtr ctx, String outfile, int page_num, int res, int type, bool append) { int output; try { if (is64bit) output = mSavePage64(ctx, outfile, page_num, res, type, append); else output = mSavePage32(ctx, outfile, page_num, res, type, append); } catch (DllNotFoundException) { /* DLL not found */ String err = "DllNotFoundException: MuPDF DLL not found 29"; mupdfDLLProblemMain(this, err); return -1; } catch (BadImageFormatException) { /* Using 32 bit with 64 or vice versa */ String err = "BadImageFormatException: Incorrect MuPDF DLL"; mupdfDLLProblemMain(this, err); return -1; } return output; } #endregion DLLErrorTrap /* Now the actual code that does some work */ public status_t Initialize() { is64bit = Environment.Is64BitOperatingSystem && Environment.Is64BitProcess; mu_object = tc_mInitialize(); if (mu_object == null) return status_t.E_FAILURE; else return status_t.S_ISOK; } public void CleanUp() { if (mu_object != null) { lock(m_lock) tc_mCleanUp(mu_object); } } public String GetText(int page_num, textout_t type) { return tc_mGetText(mu_object, page_num, type); } public void GetVersion(out String vers) { vers = tc_mGetVers(); } public int GetPageCount() { return tc_mGetPageCount(mu_object); } public bool RequiresPassword() { return tc_mRequiresPassword(mu_object); } public bool ApplyPassword(String password) { return tc_mApplyPassword(mu_object, password); } public void SetAA(AA_t AAlevel) { lock (m_lock) { tc_mSetAA(mu_object, (int)AAlevel); } } public int RenderPage(int page_num, Byte[] bmp_data, int bmp_width, int bmp_height, double scale, bool flipy, bool use_dlist, bool get_text, out BlocksText blocks, bool annotation, out Annotate_t annot_type) { int code; blocks = null; String blockcolor = "#00FFFFFF"; String linecolor = "#402572AC"; /* Debug */ //blockcolor = "#20FFFF00"; annot_type = Annotate_t.UNKNOWN; if (use_dlist) { IntPtr dlist = IntPtr.Zero; IntPtr annot_dlist = IntPtr.Zero; IntPtr text = IntPtr.Zero; int num_blocks = 0; int page_height = 0; int page_width = 0; if (get_text) { lock (m_lock) { dlist = tc_mCreateDisplayListText(mu_object, page_num, ref page_width, ref page_height, ref text, ref num_blocks); } /* If we have some text go ahead and get the bounding boxes * now. There is likely a better way to do this with passing * a structure across the boundary in a single call. ToDO */ /* Length here is the number of blocks. mupdf splits block * into lines (spans) and then these into text characters * Our goal here is to get them into a structure that we * can rapidly use in our ui display. Maintaining the block * and span stucture so that we can minimize the number of * rects that are introduced */ if (num_blocks > 0) { blocks = new BlocksText(); for (int kk = 0; kk < num_blocks; kk++) { double top_x = 0, top_y = 0, height = 0, width = 0; var block = new TextBlock(); int num_lines = tc_mGetTextBlock(text, kk, ref top_x, ref top_y, ref height, ref width); block.X = top_x; block.Y = top_y; block.Width = width; block.Height = height; block.Color = blockcolor; block.Scale = 1.0; block.PageNumber = page_num; blocks.Add(block); blocks[kk].TextLines = new List(); for (int jj = 0; jj < num_lines; jj++) { var line = new TextLine(); int num_chars = tc_mGetTextLine(text, kk, jj, ref top_x, ref top_y, ref height, ref width); line.X = top_x; line.Y = top_y; line.Width = width; line.Height = height; line.Scale = 1.0; line.Color = linecolor; blocks[kk].TextLines.Add(line); blocks[kk].TextLines[jj].TextCharacters = new List(); for (int mm = 0; mm < num_chars; mm++) { var textchars = new TextCharacter(); int character = tc_mGetTextCharacter(text, kk, jj, mm, ref top_x, ref top_y, ref height, ref width); textchars.X = top_x; textchars.Y = top_y; textchars.Width = width; textchars.Height = height; textchars.Scale = 1.0; textchars.Color = linecolor; textchars.character = System.Convert.ToChar(character).ToString(); blocks[kk].TextLines[jj].TextCharacters.Add(textchars); } } } /* We are done with the text object */ tc_mReleaseText(mu_object, text); } } else lock (m_lock) { dlist = tc_mCreateDisplayList(mu_object, page_num, ref page_width, ref page_height); } if (annotation) { lock (m_lock) { annot_dlist = tc_mCreateDisplayListAnnot(mu_object, page_num); if (annot_dlist == IntPtr.Zero) annot_type = Annotate_t.NO_ANNOTATE; else annot_type = Annotate_t.HAS_ANNOTATE; } } /* Rendering of display list can occur with other threads so unlock */ if (dlist == null) { return (int) status_t.E_FAILURE; } code = tc_mRenderPageMT(mu_object, dlist, annot_dlist, page_width, page_height, bmp_data, bmp_width, bmp_height, scale, flipy); } else { lock(m_lock) { code = tc_mRenderPage(mu_object, page_num, bmp_data, bmp_width, bmp_height, scale, flipy); } } return code; } public status_t OpenFile(string filename) { return tc_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 = tc_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 = tc_mGetContents(mu_object); } if (contents == null) contents = new List(); for (int k = 0; k < num_items; k++) { ContentItem item = new ContentItem(); item.StringMargin = tc_mGetContentsItem(k, ref len, ref page); item.Page = page; contents.Add(item); } return num_items; } public void ReleaseContents() { tc_mReleaseContents(); } public int TextSearchPage(int page_num, String needle) { int num_found; lock (m_lock) { num_found = tc_mTextSearchPage(mu_object, page_num, needle); } return num_found; } public bool GetTextSearchItem(int k, out Point top_left, out Size size_rect) { double top_x = 0, top_y = 0 , height = 0, width = 0; bool found = tc_mGetTextSearchItem(k, ref top_x, ref top_y, ref height, ref width); top_left = new Point(); size_rect = new Size(); top_left.X = top_x; top_left.Y = top_y; size_rect.Width = width; size_rect.Height = height; return found; } public void ReleaseTextSearch() { tc_mReleaseTextSearch(); } public int GetLinksPage(int page_num) { int num_found; lock (m_lock) { num_found = tc_mGetLinksPage(mu_object, page_num); } return num_found; } public void GetLinkItem(int k, out Point top_left, out Size size_rect, out String uri, out int topage, out int typea) { double top_x = 0, top_y = 0, height = 0, width = 0; int typeb = 0; int linkpage = 0; uri = tc_mGetLinkItem(k, ref top_x, ref top_y, ref height, ref width, ref linkpage, ref typeb); topage = linkpage; typea = typeb; top_left = new Point(); size_rect = new Size(); top_left.X = top_x; top_left.Y = top_y; size_rect.Width = width; size_rect.Height = height; } public void ReleaseLink() { tc_mReleaseLink(); } public void ReleaseText(IntPtr textpage) { tc_mReleaseText(mu_object, textpage); } public void HTMLSaveAs(String infile, String outfile, String password, bool has_password, bool linearize, int num_pages, System.Collections.IList pages) { if (num_pages > 0) { /* We need to do an allocation for our array of page numbers and * perform pinning to avoid GC while in the c++ code */ GCHandle pagesPtrStable; int[] page_list; page_list = new int[pages.Count]; for (int kk = 0; kk < pages.Count; kk++) { SelectPage currpage = (SelectPage)pages[kk]; page_list[kk] = currpage.Page; } pagesPtrStable = GCHandle.Alloc(page_list, GCHandleType.Pinned); tc_mExtractPages(infile, outfile, password, has_password, linearize, num_pages, pagesPtrStable.AddrOfPinnedObject()); pagesPtrStable.Free(); } else { tc_mExtractPages(infile, outfile, password, has_password, linearize, num_pages, IntPtr.Zero); } } public void PDFExtract(String infile, String outfile, String password, bool has_password, bool linearize, int num_pages, System.Collections.IList pages) { if (num_pages > 0) { /* We need to do an allocation for our array of page numbers and * perform pinning to avoid GC while in the c++ code */ GCHandle pagesPtrStable; int[] page_list; page_list = new int[pages.Count]; for (int kk = 0; kk < pages.Count; kk++) { SelectPage currpage = (SelectPage)pages[kk]; page_list[kk] = currpage.Page; } pagesPtrStable = GCHandle.Alloc(page_list, GCHandleType.Pinned); tc_mExtractPages(infile, outfile, password, has_password, linearize, num_pages, pagesPtrStable.AddrOfPinnedObject()); pagesPtrStable.Free(); } else { tc_mExtractPages(infile, outfile, password, has_password, linearize, num_pages, IntPtr.Zero); } } public gsStatus ConvertSave(gsDevice_t device, String outputFile, int num_pages, System.Collections.IList pages, int resolution) { ConvertParams_t convertparams = new ConvertParams_t(); convertparams.device = device; convertparams.outputfile = outputFile; convertparams.num_pages = num_pages; convertparams.resolution = resolution; convertparams.pages = pages; convertparams.currpage = 1; return ConvertMuPDF(convertparams); } /* Render page by page in background with progress call back */ private gsStatus ConvertMuPDF(ConvertParams_t Params) { try { if (m_worker != null && m_worker.IsBusy) { m_worker.CancelAsync(); return gsStatus.GS_BUSY; } if (m_worker == null) { m_worker = new BackgroundWorker(); m_worker.WorkerReportsProgress = true; m_worker.WorkerSupportsCancellation = true; m_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MuPDFCompleted); m_worker.ProgressChanged += new ProgressChangedEventHandler(MuPDFProgressChanged); m_worker.DoWork += new DoWorkEventHandler(MuPDFWork); } m_params = Params; m_worker.RunWorkerAsync(Params); return gsStatus.GS_READY; } catch (OutOfMemoryException e) { Console.WriteLine("Memory allocation failed during mupdf rendering\n"); return gsStatus.GS_ERROR; } } private void MuPDFCompleted(object sender, RunWorkerCompletedEventArgs e) { ConvertParams_t Value; muPDFEventArgs info; if (e.Cancelled) { Value = new ConvertParams_t(); Value.result = GS_Result_t.gsCANCELLED; info = new muPDFEventArgs(true, 100, Value); } else { Value = (ConvertParams_t)e.Result; info = new muPDFEventArgs(true, 100, Value); } mupdfUpdateMain(this, info); } private void MuPDFProgressChanged(object sender, ProgressChangedEventArgs e) { /* Callback with progress */ ConvertParams_t Value = new ConvertParams_t(); muPDFEventArgs info = new muPDFEventArgs(false, e.ProgressPercentage, Value); mupdfUpdateMain(this, info); } public void Cancel() { m_worker.CancelAsync(); } /* ToDo: do we report pages that failed? or just push on */ private void MuPDFWork(object sender, DoWorkEventArgs e) { ConvertParams_t muparams = (ConvertParams_t)e.Argument; String out_file = muparams.outputfile; int num_pages = muparams.num_pages; int resolution = muparams.resolution; var pages = muparams.pages; BackgroundWorker worker = sender as BackgroundWorker; muparams.result = GS_Result_t.gsOK; int result; for (int kk = 0; kk < num_pages; kk++) { SelectPage curr_page = (SelectPage)pages[kk]; int page_num = curr_page.Page; bool append = (kk != 0); /* Look for file extension. */ string extension = System.IO.Path.GetExtension(out_file); int len = extension.Length; String new_out_file = out_file.Substring(0, out_file.Length - len); String out_file_name = new_out_file + "_" + page_num + extension; /* Question: is lock valid when done from this worker thread? */ switch (muparams.device) { case gsDevice_t.svg: lock (this.m_lock) /* Single-page format */ result = tc_mSavePage(mu_object, out_file_name, page_num - 1, resolution, (int) mudevice_t.SVG_OUT, false); break; case gsDevice_t.pnm: lock (this.m_lock) /* Single-page format */ result = tc_mSavePage(mu_object, out_file_name, page_num - 1, resolution, (int)mudevice_t.PNM_OUT, false); break; case gsDevice_t.pclbitmap: /* Multi-page format */ lock (this.m_lock) result = tc_mSavePage(mu_object, out_file, page_num - 1, resolution, (int)mudevice_t.PCL_OUT, append); break; case gsDevice_t.pwg: /* Multi-page format */ lock (this.m_lock) result = tc_mSavePage(mu_object, out_file, page_num - 1, resolution, (int)mudevice_t.PWG_OUT, append); break; } double prog = (double) (kk+1.0)/((double) num_pages) * 100.0; worker.ReportProgress((int)prog); if (worker.CancellationPending == true) { e.Cancel = true; muparams.result = GS_Result_t.gsCANCELLED; break; } } e.Result = muparams; return; } } }