summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-11-21 12:23:59 +0000
committerRobin Watts <robin.watts@artifex.com>2016-11-23 10:01:25 +0000
commit30afe6fa458cef7a6f84020de5bd15d8ae164521 (patch)
tree9005cbc6e93c13cedf1b2243052ba11e8affe79c
parent6d138194b425c64e2177b4493fe8d2cf2ecac7ae (diff)
downloadmupdf-30afe6fa458cef7a6f84020de5bd15d8ae164521.tar.xz
First version of mu-office-lib.
-rw-r--r--include/mupdf/helpers/mu-office-lib.h599
-rw-r--r--platform/win32/mu-office-lib.vcproj810
-rw-r--r--platform/win32/mu-office-test.vcproj1058
-rw-r--r--platform/win32/mupdf.sln108
-rw-r--r--source/helpers/mu-office-lib/mu-office-lib.c1042
-rw-r--r--source/tests/mu-office-test.c288
6 files changed, 3896 insertions, 9 deletions
diff --git a/include/mupdf/helpers/mu-office-lib.h b/include/mupdf/helpers/mu-office-lib.h
new file mode 100644
index 00000000..9c4cd845
--- /dev/null
+++ b/include/mupdf/helpers/mu-office-lib.h
@@ -0,0 +1,599 @@
+/**
+ * Mu Office Library
+ *
+ * This helper layer provides an API for loading, and displaying
+ * a file. It is deliberately as identical as possible to the
+ * smart-office-lib.h header file in Smart Office to facilitate
+ * a product which can use both Smart Office and MuPDF.
+ */
+
+#ifndef MU_OFFICE_LIB_H
+#define MU_OFFICE_LIB_H
+
+/*
+ * General use
+ *
+ * This library uses threads but is not thread safe for the caller. All
+ * calls should be made from a single thread. Some calls allow the user
+ * to arrange for their own functions to be called back from the library;
+ * often the users functions will be called back from a different thread. If
+ * a call into the library is required in response to information from a
+ * callback, it is the responsibility of the user to arrange for those
+ * library calls to be made on the same thread as for other library calls.
+ * Calls back into the library from a callback are not permitted.
+ *
+ * There are two main modes of use. In interactive windowing systems, it
+ * is usual for the app developers code to be called on the main UI thread.
+ * It is from the UI thread that all library calls should be made. Such
+ * systems usually provide a way to post a call onto the UI thread. That
+ * is the best way to respond to a callback from the library.
+ *
+ * The other mode of use is for plain executables that might wish to
+ * (say) generate images of all the pages of a document. This can
+ * be acheived, without use of callbacks, using the few synchronous
+ * calls. E.g., MuOfficeDoc_getNumPages will wait for background document
+ * loading to complete before returning the total number of pages and
+ * MuOfficeRender_destroy will wait for background rendering to complete
+ * before returning.
+ */
+
+#include <stddef.h> /* For size_t */
+
+/** Error type returned from most MuOffice functions
+ *
+ * 0 means no error
+ *
+ * non-zero values mean an error occurred. The exact value is an indication
+ * of what went wrong and should be included in bug reports or support
+ * queries. Library users should not test this value except for 0,
+ * non-zero and any explicitly documented values.
+ */
+typedef int MuError;
+
+
+/** Errors returned to MuOfficeLoadingErrorFn
+ *
+ * Other values may also be returned.
+ */
+typedef enum MuOfficeDocErrorType
+{
+ MuOfficeDocErrorType_NoError = 0,
+ MuOfficeDocErrorType_UnsupportedDocumentType = 1,
+ MuOfficeDocErrorType_EmptyDocument = 2,
+ MuOfficeDocErrorType_UnableToLoadDocument = 4,
+ MuOfficeDocErrorType_UnsupportedEncryption = 5,
+ MuOfficeDocErrorType_Aborted = 6,
+ MuOfficeDocErrorType_OutOfMemory = 7,
+
+ /* FIXME: Additional ones that should be backported to
+ * smart-office-lib.h */
+ MuOfficeDocErrorType_IllegalArgument = 8,
+
+ /** A password is required to open this document.
+ *
+ * The app should provide it using MuOffice_providePassword
+ * or if it doesn't want to proceed call MuOfficeDoc_destroy or
+ * MuOfficeDoc_abortLoad.
+ */
+ MuOfficeDocErrorType_PasswordRequest = 0x1000
+} MuOfficeDocErrorType;
+
+
+/**
+ *Structure holding the detail of the layout of a bitmap. b5g6r5 is assumed.
+ */
+typedef struct MuOfficeBitmap_s
+{
+ void *memptr;
+ int width;
+ int height;
+ int lineSkip;
+} MuOfficeBitmap;
+
+
+/**
+ * Structure defining a point
+ *
+ * x x coord of point
+ * y y coord of point
+ */
+typedef struct MuOfficePoint_s
+{
+ float x;
+ float y;
+} MuOfficePoint;
+
+/**
+ * Structure defining a rectangle
+ *
+ * x x coord of top left of area within the page
+ * y y coord of top left of area within the page
+ * width width of area
+ * height height of area
+ */
+typedef struct MuOfficeBox_s
+{
+ float x;
+ float y;
+ float width;
+ float height;
+} MuOfficeBox;
+
+typedef enum MuOfficePointType
+{
+ MuOfficePointType_MoveTo,
+ MuOfficePointType_LineTo
+} MuOfficePointType;
+
+typedef struct MuOfficePathPoint
+{
+ float x;
+ float y;
+ MuOfficePointType type;
+} MuOfficePathPoint;
+
+/**
+ * Structure defining what area of a page should be rendered and to what
+ * area of the bitmap
+ *
+ * origin coordinates of the document origin within the bitmap
+ * renderArea the part of the bitmap to which to render
+ */
+typedef struct MuOfficeRenderArea_s
+{
+ MuOfficePoint origin;
+ MuOfficeBox renderArea;
+} MuOfficeRenderArea;
+
+
+typedef struct MuOfficeLib_s MuOfficeLib;
+typedef struct MuOfficeDoc_s MuOfficeDoc;
+typedef struct MuOfficePage_s MuOfficePage;
+typedef struct MuOfficeRender_s MuOfficeRender;
+
+/**
+ * Allocator function used by some functions to get blocks of memory.
+ *
+ * @param cookie data pointer passed in with the allocator.
+ * @param size the size of the required block.
+ *
+ * @returns as for malloc. (NULL implies OutOfMemory, or size == 0).
+ * Otherwise a pointer to an allocated block.
+ */
+typedef void *(MuOfficeAllocFn)(void *cookie,
+ size_t size);
+
+
+/**
+ * Callback function monitoring document loading
+ *
+ * Also called when the document is edited, either adding or
+ * removing pages, with the pagesLoaded value decreasing
+ * in the page-removal case.
+ *
+ * @param cookie the data pointer that was originally passed
+ * to MuOfficeLib_loadDocument.
+ * @param pagesLoaded the number of pages so far discovered.
+ * @param complete whether loading has completed. If this flag
+ * is set, pagesLoaded is the actual number of
+ * pages in the document.
+ */
+typedef void (MuOfficeLoadingProgressFn)(void *cookie,
+ int pagesLoaded,
+ int complete);
+
+
+/**
+ * Callback function used to monitor errors in the process of loading
+ * a document.
+ *
+ * @param cookie the data pointer that was originally passed
+ * to MuOfficeLib_loadDocument.
+ * @param error the error being reported
+ */
+typedef void (MuOfficeLoadingErrorFn)( void *cookie,
+ MuOfficeDocErrorType error);
+
+
+
+/**
+ * Callback function used to monitor page changes
+ *
+ * @param cookie the data pointer that was originally passed
+ * to MuOfficeDoc_getPage.
+ * @param area the area that has changed.
+ */
+typedef void (MuOfficePageUpdateFn)( void *cookie,
+ const MuOfficeBox *area);
+
+/**
+ * Callback function used to monitor a background render of a
+ * document page. The function is called exactly once.
+ *
+ * @param cookie the data pointer that was originally passed
+ * to MuOfficeDoc_monitorRenderProgress.
+ * @param error error returned from the rendering process
+ */
+typedef void (MuOfficeRenderProgressFn)(void *cookie,
+ MuError error);
+
+/**
+ * Document types
+ *
+ * Keep in sync with smart-office-lib.h
+ */
+typedef enum
+{
+ MuOfficeDocType_PDF,
+ MuOfficeDocType_XPS,
+ MuOfficeDocType_IMG
+} MuOfficeDocType;
+
+
+/**
+ * The possible results of a save operation
+ */
+typedef enum MuOfficeSaveResult
+{
+ MuOfficeSave_Succeeded,
+ MuOfficeSave_Error,
+ MuOfficeSave_Cancelled
+}
+MuOfficeSaveResult;
+
+
+/**
+ * Callback function used to monitor save operations.
+ *
+ * @param cookie the data pointer that was oringinally passed to
+ * MuOfficeDoc_save.
+ * @param result the result of the save operation
+ */
+typedef void (MuOfficeSaveResultFn)( void *cookie,
+ MuOfficeSaveResult result);
+
+
+/**
+ * Create a MuOfficeLib instance.
+ *
+ * @param pMu address of variable to
+ * receive the created instance
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeLib_create(MuOfficeLib **pMu);
+
+/**
+ * Destroy a MuOfficeLib instance
+ *
+ * @param mu the instance to destroy
+ */
+void MuOfficeLib_destroy(MuOfficeLib *mu);
+
+/**
+ * Find the type of a file given it's filename extension.
+ *
+ * @param path path to the file (in utf8)
+ *
+ * @return a valid MuOfficeDocType value, or MuOfficeDocType_Other
+ */
+MuOfficeDocType MuOfficeLib_getDocTypeFromFileExtension(const char *path);
+
+/**
+ * Return a list of file extensions supported by Mu Office library.
+ *
+ * @return comma-delimited list of extensions, without the leading ".".
+ * The caller should free the returned pointer..
+ */
+char * MuOfficeLib_getSupportedFileExtensions(void);
+
+/**
+ * Load a document
+ *
+ * Call will return immediately, leaving the document loading
+ * in the background
+ *
+ * @param mu a MuOfficeLib instance
+ * @param path path to the file to load (in utf8)
+ * @param progressFn callback for monitoring progress
+ * @param errorFn callback for monitoring errors
+ * @param cookie a pointer to pass back to the callbacks
+ * @param pDoc address for return of a MuOfficeDoc object
+ *
+ * @return error indication - 0 for success
+ *
+ * The progress callback may be called several times, with increasing
+ * values of pagesLoaded. Unless MuOfficeDoc_destroy is called,
+ * before loading completes, a call with "completed" set to true
+ * is guaranteed.
+ *
+ * Once MuOfficeDoc_destroy is called there will be no
+ * further callbacks.
+ *
+ * Alternatively, in a synchronous context, MuOfficeDoc_getNumPages
+ * can be called to wait for loading to complete and return the total
+ * number of pages. In this mode of use, progressFn can be NULL. 
+ */
+MuError MuOfficeLib_loadDocument(MuOfficeLib *mu,
+ const char *path,
+ MuOfficeLoadingProgressFn *progressFn,
+ MuOfficeLoadingErrorFn *errorFn,
+ void *cookie,
+ MuOfficeDoc **pDoc);
+
+
+/**
+ * Provide the password for a document
+ *
+ * This function should be called to provide a password with a document
+ * error if MuOfficeError_PasswordRequired is received.
+ *
+ * If a password is requested again, this means the password was incorrect.
+ *
+ * @param doc the document object
+ * @param password the password (UTF8 encoded)
+ * @return error indication - 0 for success
+ */
+int MuOfficeDoc_providePassword(MuOfficeDoc *doc, const char *password);
+
+
+/**
+ * Return the type of an open document
+ *
+ * @param doc the document object
+ *
+ * @return the document type
+ */
+MuOfficeDocType MuOfficeDoc_docType(MuOfficeDoc *doc);
+
+
+/**
+ * Return the number of pages of a document
+ *
+ * This function waits for document loading to complete before returning
+ * the result. It may block the calling thread for a signficant period of
+ * time. To avoid blocking, this call should be avoided in favour of using
+ * the MuOfficeLib_loadDocument callbacks to monitor loading.
+ *
+ * If background loading fails, the associated error will be returned
+ * from this call.
+ *
+ * @param doc the document
+ * @param pNumPages address for return of the number of pages
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_getNumPages(MuOfficeDoc *doc, int *pNumPages);
+
+
+/**
+ * Determine if the document has been modified
+ *
+ * @param doc the document
+ *
+ * @return modified flag
+ */
+int MuOfficeDoc_hasBeenModified(MuOfficeDoc *doc);
+
+
+/**
+ * Start a save operation
+ *
+ * @param doc the document
+ * @param path path of the file to which to save
+ * @param resultFn callback used to report completion
+ * @param cookie a pointer to pass to the callback
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_save(MuOfficeDoc *doc,
+ const char *path,
+ MuOfficeSaveResultFn *resultFn,
+ void *cookie);
+
+
+/**
+ * Stop a document loading. The document is not destroyed, but
+ * no further content will be read from the file.
+ *
+ * @param doc the MuOfficeDoc object
+ */
+void MuOfficeDoc_abortLoad(MuOfficeDoc *doc);
+
+
+/**
+ * Destroy a MuOfficeDoc object. Loading of the document is shutdown
+ * and no further callbacks will be issued for the specified object.
+ *
+ * @param doc the MuOfficeDoc object
+ */
+void MuOfficeDoc_destroy(MuOfficeDoc *doc);
+
+
+/**
+ * Get a page of a document
+ *
+ * @param doc the document object
+ * @param pageNumber the number of the page to load (lying in the
+ * range 0 to one less than the number of pages)
+ * @param updateFn Function to be called back when the page updates
+ * @param cookie Opaque value to pass for any updates
+ * @param pPage Address for return of the page object
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_getPage( MuOfficeDoc *doc,
+ int pageNumber,
+ MuOfficePageUpdateFn *updateFn,
+ void *cookie,
+ MuOfficePage **pPage);
+
+
+/**
+ * Destroy a page object
+ *
+ * Note this does not delete or remove the page from the document.
+ * It simply destroys the page object which is merely a reference
+ * to the page.
+ *
+ * @param page the page object
+ */
+void MuOfficePage_destroy(MuOfficePage *page);
+
+
+/**
+ * Get the size of a page in pixels
+ *
+ * This returns the size of the page in pixels. Pages can be rendered
+ * with a zoom factor. The returned value is the size of bitmap
+ * appropriate for rendering with a zoom of 1.0 and corresponds to
+ * 90 dpi. The returned values are not necessarily whole numbers.
+ *
+ * @param page the page object
+ * @param pWidth address for return of the width
+ * @param pHeight address for return of the height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_getSize( MuOfficePage *page,
+ float *pWidth,
+ float *pHeight);
+
+
+/**
+ * Return the zoom factors necessary to render at to a given
+ * size in pixels. (deprecated)
+ *
+ * @param page the page object
+ * @param width the desired width
+ * @param height the desired height
+ * @param pXZoom Address for return of zoom necessary to fit width
+ * @param pYZoom Address for return of zoom necessary to fit height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_calculateZoom( MuOfficePage *page,
+ int width,
+ int height,
+ float *pXZoom,
+ float *pYZoom);
+
+
+/**
+ * Get the size of a page in pixels for a specified zoom factor
+ * (deprecated)
+ *
+ * This returns the size of bitmap that should be used to display
+ * the entire page at the given zoom factor. A zoom of 1.0
+ * corresponds to 90 dpi.
+ *
+ * @param page the page object
+ * @param zoom the zoom factor
+ * @param pWidth address for return of the width
+ * @param pHeight address for return of the height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_getSizeForZoom( MuOfficePage *page,
+ float zoom,
+ int *pWidth,
+ int *pHeight);
+
+
+/**
+ * Schedule the rendering of an area of document page to
+ * an area of a bitmap.
+ *
+ * The alignment between page and bitmap is defined by specifying
+ * document's origin within the bitmap, possibly either positive or
+ * negative. A render object is returned via which the process can
+ * be monitored or terminated.
+ *
+ * The progress function is called exactly once per render in either
+ * the success or failure case.
+ *
+ * Note that, since a render object represents a running thread that
+ * needs access to the page, document, and library objects, it is important
+ * to call MuOfficeRender_destroy, not only before using or deallocating
+ * the bitmap, but also before calling MuOfficePage_destroy, etc..
+ *
+ * @param page the page to render
+ * @param zoom the zoom factor
+ * @param bitmap the bitmap
+ * @param area area to render
+ * @param progressFn the progress callback function
+ * @param cookie a pointer to pass to the callback function
+ * @param pRender Address for return of the render object
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_render( MuOfficePage *page,
+ float zoom,
+ const MuOfficeBitmap *bitmap,
+ const MuOfficeRenderArea *area,
+ MuOfficeRenderProgressFn *progressFn,
+ void *cookie,
+ MuOfficeRender **pRender);
+
+
+/**
+ * Destroy a render
+ *
+ * This call destroys a MuOfficeRender object, aborting any current
+ * render.
+ *
+ * This call is intended to support an app dealing with a user quickly
+ * flicking through document pages. A render may be sheduled but, before
+ * completion, be found not to be needed. In that case the bitmap will
+ * need to be reused, which requires any existing render to be aborted.
+ * The call to MuOfficeRender_destroy will cut short the render and
+ * allow the bitmap to be reused immediately.
+ *
+ * @note If an active render thread is destroyed, it will be aborted.
+ * While fast, this is not an instant operation. For maximum
+ * responsiveness, it is best to 'abort' as soon as you realise you
+ * don't need the render, and to destroy when you get the callback.
+ *
+ * @param render The render object
+ */
+void MuOfficeRender_destroy(MuOfficeRender *render);
+
+/**
+ * Abort a render
+ *
+ * This call aborts any rendering currently underway. The 'render
+ * complete' callback (if any) given when the render was created will
+ * still be called. If a render has completed, this call will have no
+ * effect.
+ *
+ * This call will not block to wait for the render thread to stop, but
+ * will cause it to stop as soon as it can in the background.
+ *
+ * @note It is important not to start any new render to the same bitmap
+ * until the callback comes in (or until waitUntilComplete returns), as
+ * otherwise you can have multiple renders drawing to the same bitmap
+ * with unpredictable consequences.
+ *
+ * @param render The render object to abort
+ */
+void MuOfficeRender_abort(MuOfficeRender *render);
+
+/**
+ * Wait for a render to complete.
+ *
+ * This call will not return until rendering is complete, so on return
+ * the bitmap will contain the page image (assuming the render didn't
+ * run into an error condition) and will not be used further by any
+ * background processing. Any error during rendering will be returned
+ * from this function.
+ *
+ * This call may block the calling thread for a significant period of
+ * time. To avoid blocking, supply a progress-monitoring callback
+ * function to MuOfficePage_render.
+ *
+ * @param render The render object to destroy
+ * @return render error condition - 0 for no error.
+ */
+MuError MuOfficeRender_waitUntilComplete(MuOfficeRender *render);
+
+#endif /* SMART_OFFICE_LIB_H */
diff --git a/platform/win32/mu-office-lib.vcproj b/platform/win32/mu-office-lib.vcproj
new file mode 100644
index 00000000..fc5a8797
--- /dev/null
+++ b/platform/win32/mu-office-lib.vcproj
@@ -0,0 +1,810 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="mu-office-lib"
+ ProjectGUID="{FFF91365-C9BA-4F40-AE2B-EF93702871B2}"
+ RootNamespace="mu-office-lib"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32;MEMENTO=1;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=" "
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Memento|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32;MEMENTO=1"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Memento|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;MEMENTO=1;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=" "
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;_CRT_SECURE_NO_WARNINGS"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=" "
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="ReleaseCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="ReleaseCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;_CRT_SECURE_NO_WARNINGS"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="MementoCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN32;MEMENTO=1"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\$(ProjectName).lib"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="MementoCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include\mupdf\mu-office-lib;..\..\include"
+ PreprocessorDefinitions="WIN64;MEMENTO=1;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ IgnoreAllDefaultLibraries="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath="..\..\include\mupdf\helpers\mu-office-lib.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="source"
+ >
+ <File
+ RelativePath="..\..\source\helpers\mu-office-lib\mu-office-lib.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/platform/win32/mu-office-test.vcproj b/platform/win32/mu-office-test.vcproj
new file mode 100644
index 00000000..bd64017b
--- /dev/null
+++ b/platform/win32/mu-office-test.vcproj
@@ -0,0 +1,1058 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="mu-office-test"
+ ProjectGUID="{FB51171B-B10E-4EAC-8FFA-19226A1828A3}"
+ RootNamespace="mupdf"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Memento|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;MEMENTO=1;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Memento|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;MEMENTO=1;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugGProof|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugGProof|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="DebugCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="ReleaseCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="ReleaseCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="MementoCommercial|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;MEMENTO=1;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="MementoCommercial|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)\$(ProjectName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\include"
+ PreprocessorDefinitions="FZ_LARGEFILE;MEMENTO=1;DEBUG=1;USE_OUTPUT_DEBUG_STRING"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\source\tests\mu-office-test.c"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/platform/win32/mupdf.sln b/platform/win32/mupdf.sln
index cccd611a..723b8dea 100644
--- a/platform/win32/mupdf.sln
+++ b/platform/win32/mupdf.sln
@@ -10,10 +10,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libthirdparty", "libthirdpa
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmupdf", "libmupdf.vcproj", "{5F615F91-DFF8-4F05-BF48-6222B7D86519}"
ProjectSection(ProjectDependencies) = postProject
- {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
- {A5053AA7-02E5-4903-B596-04F17AEB1526} = {A5053AA7-02E5-4903-B596-04F17AEB1526}
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
{B0091365-C9BA-4F40-AE2B-EF93702871B2} = {B0091365-C9BA-4F40-AE2B-EF93702871B2}
+ {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
+ {A5053AA7-02E5-4903-B596-04F17AEB1526} = {A5053AA7-02E5-4903-B596-04F17AEB1526}
+ {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mudraw", "mudraw.vcproj", "{0B51171B-B10E-4EAC-8FFA-19226A1828A3}"
@@ -32,8 +32,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcurl", "..\..\thirdparty
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf-curl", "mupdf-curl.vcproj", "{27B53E5C-ACAB-423C-854E-BECE56D73544}"
ProjectSection(ProjectDependencies) = postProject
- {87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588}
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mujstest", "mujstest.vcproj", "{21E28758-E4D2-4B84-8EC5-B631CEE66B30}"
@@ -45,8 +45,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libglfw", "libglfw.vcproj",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf-gl", "mupdf-gl.vcproj", "{CE3A76A8-A28F-4991-8FB9-C9453D922037}"
ProjectSection(ProjectDependencies) = postProject
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
{A1B75D29-9F5C-4A0F-B368-322A10477D0C} = {A1B75D29-9F5C-4A0F-B368-322A10477D0C}
+ {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfonts", "libfonts.vcproj", "{52DCAB29-C8EE-4422-954C-29AFA6B33E22}"
@@ -56,27 +56,38 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libfonts", "libfonts.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "muraster", "muraster.vcproj", "{0FDC74D7-D18C-45CE-94D6-EDFCC5A0CDF2}"
ProjectSection(ProjectDependencies) = postProject
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
{52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
+ {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "javaviewerlib", "javaviewerlib.vcproj", "{3DB35F2D-9679-4DED-BA0C-240A4E6E6674}"
ProjectSection(ProjectDependencies) = postProject
- {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "javaviewer", "javaviewer.vcproj", "{FB8DC595-90A5-44D6-9FFF-2BDFA912FD8C}"
ProjectSection(ProjectDependencies) = postProject
- {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
- {3DB35F2D-9679-4DED-BA0C-240A4E6E6674} = {3DB35F2D-9679-4DED-BA0C-240A4E6E6674}
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {3DB35F2D-9679-4DED-BA0C-240A4E6E6674} = {3DB35F2D-9679-4DED-BA0C-240A4E6E6674}
+ {52DCAB29-C8EE-4422-954C-29AFA6B33E22} = {52DCAB29-C8EE-4422-954C-29AFA6B33E22}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libluratech", "libluratech.vcproj", "{B0091365-C9BA-4F40-AE2B-EF93702871B2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmuthreads", "libmuthreads.vcproj", "{DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mu-office-lib", "mu-office-lib.vcproj", "{FFF91365-C9BA-4F40-AE2B-EF93702871B2}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B} = {DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mu-office-test", "mu-office-test.vcproj", "{FB51171B-B10E-4EAC-8FFA-19226A1828A3}"
+ ProjectSection(ProjectDependencies) = postProject
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2} = {FFF91365-C9BA-4F40-AE2B-EF93702871B2}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -708,6 +719,85 @@ Global
{DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B}.ReleaseOpenssl|Win32.ActiveCfg = ReleaseCommercial|x64
{DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B}.ReleaseOpenssl|x64.ActiveCfg = ReleaseCommercial|x64
{DE21FA8A-FC8A-47E0-87E4-DCE8808BFC9B}.ReleaseOpenssl|x64.Build.0 = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Debug|Win32.Build.0 = Debug|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Debug|x64.ActiveCfg = Debug|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Debug|x64.Build.0 = Debug|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugCommercial|Win32.ActiveCfg = DebugCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugCommercial|Win32.Build.0 = DebugCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugCommercial|x64.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugCommercial|x64.Build.0 = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugGProof|Win32.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugGProof|x64.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugGProof|x64.Build.0 = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugJava|Win32.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugJava|x64.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugJava|x64.Build.0 = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugOpenssl|Win32.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugOpenssl|x64.ActiveCfg = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.DebugOpenssl|x64.Build.0 = DebugCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Memento|Win32.ActiveCfg = Memento|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Memento|Win32.Build.0 = Memento|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Memento|x64.ActiveCfg = Memento|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Memento|x64.Build.0 = Memento|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.MementoCommercial|Win32.ActiveCfg = MementoCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.MementoCommercial|Win32.Build.0 = MementoCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.MementoCommercial|x64.ActiveCfg = MementoCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.MementoCommercial|x64.Build.0 = MementoCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Release|Win32.ActiveCfg = Release|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Release|Win32.Build.0 = Release|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Release|x64.ActiveCfg = Release|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.Release|x64.Build.0 = Release|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseCommercial|Win32.ActiveCfg = ReleaseCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseCommercial|Win32.Build.0 = ReleaseCommercial|Win32
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseCommercial|x64.ActiveCfg = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseCommercial|x64.Build.0 = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseJava|Win32.ActiveCfg = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseJava|x64.ActiveCfg = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseJava|x64.Build.0 = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseOpenssl|Win32.ActiveCfg = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseOpenssl|x64.ActiveCfg = ReleaseCommercial|x64
+ {FFF91365-C9BA-4F40-AE2B-EF93702871B2}.ReleaseOpenssl|x64.Build.0 = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Debug|Win32.Build.0 = Debug|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Debug|x64.ActiveCfg = Debug|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Debug|x64.Build.0 = Debug|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugCommercial|Win32.ActiveCfg = DebugCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugCommercial|Win32.Build.0 = DebugCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugCommercial|x64.ActiveCfg = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugCommercial|x64.Build.0 = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugGProof|Win32.ActiveCfg = DebugGProof|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugGProof|Win32.Build.0 = DebugGProof|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugGProof|x64.ActiveCfg = DebugGProof|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugGProof|x64.Build.0 = DebugGProof|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugJava|Win32.ActiveCfg = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugJava|x64.ActiveCfg = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugJava|x64.Build.0 = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugOpenssl|Win32.ActiveCfg = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugOpenssl|x64.ActiveCfg = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.DebugOpenssl|x64.Build.0 = DebugCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Memento|Win32.ActiveCfg = Memento|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Memento|Win32.Build.0 = Memento|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Memento|x64.ActiveCfg = Memento|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Memento|x64.Build.0 = Memento|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.MementoCommercial|Win32.ActiveCfg = MementoCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.MementoCommercial|Win32.Build.0 = MementoCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.MementoCommercial|x64.ActiveCfg = MementoCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.MementoCommercial|x64.Build.0 = MementoCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|Win32.ActiveCfg = Release|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|Win32.Build.0 = Release|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|x64.ActiveCfg = Release|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|x64.Build.0 = Release|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseCommercial|Win32.ActiveCfg = ReleaseCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseCommercial|Win32.Build.0 = ReleaseCommercial|Win32
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseCommercial|x64.ActiveCfg = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseCommercial|x64.Build.0 = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseJava|Win32.ActiveCfg = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseJava|x64.ActiveCfg = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseJava|x64.Build.0 = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseOpenssl|Win32.ActiveCfg = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseOpenssl|x64.ActiveCfg = ReleaseCommercial|x64
+ {FB51171B-B10E-4EAC-8FFA-19226A1828A3}.ReleaseOpenssl|x64.Build.0 = ReleaseCommercial|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/source/helpers/mu-office-lib/mu-office-lib.c b/source/helpers/mu-office-lib/mu-office-lib.c
new file mode 100644
index 00000000..157e84e9
--- /dev/null
+++ b/source/helpers/mu-office-lib/mu-office-lib.c
@@ -0,0 +1,1042 @@
+/**
+ * Mu Office Library
+ *
+ * Provided access to the core document, loading, displaying and
+ * editing routines
+ *
+ * Intended for use with native UI
+ */
+
+#include "mupdf/fitz.h"
+#include "mupdf/pdf.h"
+#include "mupdf/helpers/mu-office-lib.h"
+#include "mupdf/helpers/mu-threads.h"
+#include "mupdf/memento.h"
+
+enum
+{
+ MuError_OK = 0,
+ MuError_OOM = -1,
+ MuError_BadNull = -2,
+ MuError_Generic = -3,
+ MuError_NotImplemented = -4,
+ MuError_PasswordPending = -5,
+};
+
+enum {
+ LAYOUT_W = 450,
+ LAYOUT_H = 600,
+ LAYOUT_EM = 12
+};
+
+#ifdef DISABLE_MUTHREADS
+#error "mu-office-lib requires threading to be enabled"
+#endif
+
+/*
+ If we are building as part of a smartoffice build, then we
+ should appeal to Pal_Mem_etc to get memory. If not, then
+ we should use malloc instead.
+
+ FIXME: Allow for something other than malloc/calloc/realloc/
+ free here.
+*/
+#ifndef SMARTOFFICE_BUILD
+void *Pal_Mem_calloc(unsigned int num, size_t size)
+{
+ return calloc(num, size);
+}
+
+void *Pal_Mem_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void *Pal_Mem_realloc(void *ptr, size_t size)
+{
+ return realloc(ptr, size);
+}
+
+void Pal_Mem_free(void *address)
+{
+ free(address);
+}
+#endif
+
+/*
+ All MuPDFs allocations are redirected through the
+ following functions.
+*/
+static void *muoffice_malloc(void *arg, size_t size)
+{
+ return Pal_Mem_malloc(size);
+}
+
+static void *muoffice_realloc(void *arg, void *old, size_t size)
+{
+ return Pal_Mem_realloc(old, size);
+}
+
+static void muoffice_free(void *arg, void *ptr)
+{
+ Pal_Mem_free(ptr);
+}
+
+static fz_alloc_context muoffice_alloc =
+{
+ /* user */
+ NULL,
+
+ /* void *(*malloc)(void *, size_t); */
+ muoffice_malloc,
+
+ /* void *(*realloc)(void *, void *, size_t); */
+ muoffice_realloc,
+
+ /* void (*free)(void *, void *); */
+ muoffice_free
+};
+
+/*
+ All MuPDFs locking is done using the following functions
+*/
+static void muoffice_lock(void *user, int lock);
+
+static void muoffice_unlock(void *user, int lock);
+
+static fz_locks_context muoffice_locks =
+{
+ /* void *user; */
+ NULL,
+
+ /* void (*lock)(void *user, int lock); */
+ muoffice_lock,
+
+ /* void (*unlock)(void *user, int lock); */
+ muoffice_unlock
+};
+
+#define LOCKS_INIT() init_muoffice_locks()
+#define LOCKS_FIN() fin_muoffice_locks()
+
+static mu_mutex mutexes[FZ_LOCK_MAX];
+
+static void muoffice_lock(void *user, int lock)
+{
+ mu_lock_mutex(&mutexes[lock]);
+}
+
+static void muoffice_unlock(void *user, int lock)
+{
+ mu_unlock_mutex(&mutexes[lock]);
+}
+
+static void fin_muoffice_locks(void)
+{
+ int i;
+
+ for (i = 0; i < FZ_LOCK_MAX; i++)
+ mu_destroy_mutex(&mutexes[i]);
+}
+
+static fz_locks_context *init_muoffice_locks(void)
+{
+ int i;
+ int failed = 0;
+
+ for (i = 0; i < FZ_LOCK_MAX; i++)
+ failed |= mu_create_mutex(&mutexes[i]);
+
+ if (failed)
+ {
+ fin_muoffice_locks();
+ return NULL;
+ }
+
+ return &muoffice_locks;
+}
+
+struct MuOfficeLib_s
+{
+ fz_context *ctx;
+};
+
+
+MuError MuOfficeLib_create(MuOfficeLib **pMu)
+{
+ MuOfficeLib *inst;
+ fz_locks_context *locks;
+
+ if (pMu == NULL)
+ return MuOfficeDocErrorType_IllegalArgument;
+
+ locks = init_muoffice_locks();
+ if (locks == NULL)
+ return MuOfficeDocErrorType_OutOfMemory;
+
+ inst = Pal_Mem_calloc(1, sizeof(MuOfficeLib));
+ if (inst == NULL)
+ goto Fail;
+
+ inst->ctx = fz_new_context(&muoffice_alloc, locks, FZ_STORE_DEFAULT);
+ if (inst->ctx == NULL)
+ goto Fail;
+
+ fz_try(inst->ctx)
+ fz_register_document_handlers(inst->ctx);
+ fz_catch(inst->ctx)
+ goto Fail;
+
+ *pMu = inst;
+
+ return MuOfficeDocErrorType_NoError;
+
+Fail:
+ if (inst)
+ {
+ fin_muoffice_locks();
+ Pal_Mem_free(inst);
+ }
+ return MuOfficeDocErrorType_OutOfMemory;
+}
+
+/**
+ * Destroy a MuOfficeLib instance
+ *
+ * @param so the instance to destroy
+ */
+void MuOfficeLib_destroy(MuOfficeLib *so)
+{
+ if (so == NULL)
+ return;
+
+ fz_drop_context(so->ctx);
+
+ Pal_Mem_free(so);
+}
+
+/**
+ * Find the type of a file given it's filename extension.
+ *
+ * @param path path to the file (in utf8)
+ *
+ * @return a valid MuOfficeDocType value, or MuOfficeDocType_Other
+ */
+MuOfficeDocType MuOfficeLib_getDocTypeFromFileExtension(const char *path)
+{
+ return /* FIXME */MuOfficeDocType_PDF;
+}
+
+/**
+ * Return a list of file extensions supported by Mu Office library.
+ *
+ * @return comma-delimited list of extensions, without the leading ".".
+ * The caller should free the returned pointer..
+ */
+char * MuOfficeLib_getSupportedFileExtensions(void)
+{
+ /* FIXME */
+ return NULL;
+}
+
+struct MuOfficeDoc_s
+{
+ MuOfficeLib *mu;
+ fz_context *ctx;
+ MuOfficeLoadingProgressFn *progress;
+ MuOfficeLoadingErrorFn *error;
+ void *cookie;
+ char *path;
+ char *password;
+ mu_semaphore password_sem;
+ mu_thread thread;
+ int needs_password;
+ int aborted;
+ fz_document *doc;
+
+ MuOfficePage *pages;
+};
+
+struct MuOfficePage_s
+{
+ MuOfficePage *next;
+ MuOfficeDoc *doc;
+ int pageNum;
+ void *cookie;
+ MuOfficePageUpdateFn *updateFn;
+ fz_page *page;
+ fz_display_list *list;
+};
+
+struct MuOfficeRender_s
+{
+ MuOfficePage *page;
+ float zoom;
+ const MuOfficeBitmap *bitmap;
+ int area_valid;
+ MuOfficeRenderArea area;
+ MuOfficeRenderProgressFn *progress;
+ MuError error;
+ mu_thread thread;
+ void *cookie;
+ fz_cookie mu_cookie;
+};
+
+static void load_worker(void *arg)
+{
+ MuOfficeDoc *doc = (MuOfficeDoc *)arg;
+ int numPages = 0;
+ fz_context *ctx = fz_clone_context(doc->ctx);
+ int err = 0;
+
+ if (ctx == NULL)
+ {
+ return;
+ }
+
+ fz_try(ctx)
+ {
+ doc->doc = fz_open_document(ctx, doc->path);
+ doc->needs_password = fz_needs_password(ctx, doc->doc);
+ }
+ fz_catch(ctx)
+ {
+ err = MuOfficeDocErrorType_UnsupportedDocumentType;
+ goto fail;
+ }
+
+ fz_try(ctx)
+ {
+ if (doc->needs_password && doc->error)
+ {
+ do
+ {
+ doc->error(doc->cookie, MuOfficeDocErrorType_PasswordRequest);
+ mu_wait_semaphore(&doc->password_sem);
+ if (doc->aborted)
+ break;
+ doc->needs_password = (fz_authenticate_password(ctx, doc->doc, doc->password) != 0);
+ Pal_Mem_free(doc->password);
+ doc->password = NULL;
+ }
+ while (doc->needs_password);
+ }
+
+ fz_layout_document(ctx, doc->doc, LAYOUT_W, LAYOUT_H, LAYOUT_EM);
+
+ numPages = fz_count_pages(ctx, doc->doc);
+ }
+ fz_catch(ctx)
+ err = MuOfficeDocErrorType_UnableToLoadDocument;
+
+fail:
+ if (err)
+ doc->error(doc->cookie, err);
+
+ if (doc->progress)
+ doc->progress(doc->cookie, numPages, 1);
+
+ fz_drop_context(ctx);
+}
+
+/**
+ * Load a document
+ *
+ * Call will return immediately, leaving the document loading
+ * in the background
+ *
+ * @param so a MuOfficeLib instance
+ * @param path path to the file to load (in utf8)
+ * @param progressFn callback for monitoring progress
+ * @param errorFn callback for monitoring errors
+ * @param cookie a pointer to pass back to the callbacks
+ * @param pDoc address for return of a MuOfficeDoc object
+ *
+ * @return error indication - 0 for success
+ *
+ * The progress callback may be called several times, with increasing
+ * values of pagesLoaded. Unless MuOfficeDoc_destroy is called,
+ * before loading completes, a call with "completed" set to true
+ * is guaranteed.
+ *
+ * Once MuOfficeDoc_destroy is called there will be no
+ * further callbacks.
+ *
+ * Alternatively, in a synchronous context, MuOfficeDoc_getNumPages
+ * can be called to wait for loading to complete and return the total
+ * number of pages. In this mode of use, progressFn can be NULL. 
+ */
+MuError MuOfficeLib_loadDocument( MuOfficeLib *mu,
+ const char *path,
+ MuOfficeLoadingProgressFn *progressFn,
+ MuOfficeLoadingErrorFn *errorFn,
+ void *cookie,
+ MuOfficeDoc **pDoc)
+{
+ MuOfficeDoc *doc;
+ fz_context *ctx;
+
+ if (mu == NULL || pDoc == NULL)
+ return MuOfficeDocErrorType_IllegalArgument;
+
+ *pDoc = NULL;
+
+ doc = Pal_Mem_calloc(1, sizeof(*doc));
+ if (doc == NULL)
+ return MuOfficeDocErrorType_NoError;
+
+ ctx = mu->ctx;
+ doc->mu = mu;
+ doc->ctx = fz_clone_context(ctx);
+ doc->progress = progressFn;
+ doc->error = errorFn;
+ doc->cookie = cookie;
+ doc->path = fz_strdup(ctx, path);
+ if (mu_create_semaphore(&doc->password_sem))
+ goto fail;
+
+ if (mu_create_thread(&doc->thread, load_worker, doc))
+ goto fail;
+
+ *pDoc = doc;
+
+ return MuError_OK;
+fail:
+ mu_destroy_semaphore(&doc->password_sem);
+ Pal_Mem_free(doc);
+
+ return MuError_OOM;
+}
+
+/**
+ * Provide the password for a document
+ *
+ * This function should be called to provide a password with a document
+ * error of MuOfficeError_PasswordRequired is received.
+ *
+ * If a password is requested again, this means the password was incorrect.
+ *
+ * @param doc the document object
+ * @param password the password (UTF8 encoded)
+ * @return error indication - 0 for success
+ */
+int MuOfficeDoc_providePassword(MuOfficeDoc *doc, const char *password)
+{
+ size_t len;
+
+ if (doc->password)
+ return MuError_PasswordPending;
+ if (!password)
+ password = "";
+
+ len = strlen(password);
+ doc->password = Pal_Mem_malloc(len+1);
+ strcpy(doc->password, password);
+ mu_trigger_semaphore(&doc->password_sem);
+
+ return MuError_OK;
+}
+
+
+/**
+ * Return the type of an open document
+ *
+ * @param doc the document object
+ *
+ * @return the document type
+ */
+MuOfficeDocType MuOfficeDoc_docType(MuOfficeDoc *doc)
+{
+ return /* FIXME */MuOfficeDocType_PDF;
+}
+
+
+static void
+ensure_doc_loaded(MuOfficeDoc *doc)
+{
+ if (doc == NULL)
+ return;
+
+ mu_destroy_thread(&doc->thread);
+}
+
+
+/**
+ * Return the number of pages of a document
+ *
+ * This function waits for document loading to complete before returning
+ * the result. It may block the calling thread for a signficant period of
+ * time. To avoid blocking, this call should be avoided in favour of using
+ * the MuOfficeLib_loadDocument callbacks to monitor loading.
+ *
+ * If background loading fails, the associated error will be returned
+ * from this call.
+ *
+ * @param doc the document
+ * @param pNumPages address for return of the number of pages
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_getNumPages(MuOfficeDoc *doc, int *pNumPages)
+{
+ fz_context *ctx;
+ MuError err = MuError_OK;
+
+ if (doc == NULL)
+ {
+ *pNumPages = 0;
+ return MuError_BadNull;
+ }
+
+ ensure_doc_loaded(doc);
+
+ ctx = doc->ctx;
+
+ fz_try(ctx)
+ {
+ *pNumPages = fz_count_pages(ctx, doc->doc);
+ }
+ fz_catch(ctx)
+ {
+ err = MuError_Generic;
+ }
+
+ return err;
+}
+
+
+/**
+ * Determine if the document has been modified
+ *
+ * @param doc the document
+ *
+ * @return modified flag
+ */
+int MuOfficeDoc_hasBeenModified(MuOfficeDoc *doc)
+{
+ fz_context *ctx;
+ pdf_document *pdoc;
+ int modified = 0;
+
+ if (doc == NULL)
+ return 0;
+
+ ensure_doc_loaded(doc);
+
+ ctx = doc->ctx;
+ pdoc = pdf_specifics(ctx, doc->doc);
+
+ if (pdoc == NULL)
+ return 0;
+
+ fz_try(ctx)
+ modified = pdf_has_unsaved_changes(ctx, pdoc);
+ fz_catch(ctx)
+ modified = 0;
+
+ return modified;
+}
+
+
+/**
+ * Start a save operation
+ *
+ * @param doc the document
+ * @param path path of the file to which to save
+ * @param resultFn callback used to report completion
+ * @param cookie a pointer to pass to the callback
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_save( MuOfficeDoc *doc,
+ const char *path,
+ MuOfficeSaveResultFn *resultFn,
+ void *cookie)
+{
+ return MuError_NotImplemented; /* FIXME */
+}
+
+
+/**
+ * Stop a document loading. The document is not destroyed, but
+ * no further content will be read from the file.
+ *
+ * @param doc the MuOfficeDoc object
+ */
+void MuOfficeDoc_abortLoad(MuOfficeDoc *doc)
+{
+ fz_context *ctx;
+
+ if (doc == NULL)
+ return;
+
+ ctx = doc->ctx;
+ doc->aborted = 1;
+ mu_trigger_semaphore(&doc->password_sem);
+}
+
+
+/**
+ * Destroy a MuOfficeDoc object. Loading of the document is shutdown
+ * and no further callbacks will be issued for the specified object.
+ *
+ * @param doc the MuOfficeDoc object
+ */
+void MuOfficeDoc_destroy(MuOfficeDoc *doc)
+{
+ MuOfficeDoc_abortLoad(doc);
+ mu_destroy_thread(&doc->thread);
+ mu_destroy_semaphore(&doc->password_sem);
+
+ fz_drop_document(doc->ctx, doc->doc);
+ fz_drop_context(doc->ctx);
+ Pal_Mem_free(doc->path);
+ Pal_Mem_free(doc);
+}
+
+/**
+ * Get a page of a document
+ *
+ * @param doc the document object
+ * @param pageNumber the number of the page to load (lying in the
+ * range 0 to one less than the number of pages)
+ * @param updateFn Function to be called back when the page updates
+ * @param cookie Opaque value to pass for any updates
+ * @param pPage Address for return of the page object
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficeDoc_getPage( MuOfficeDoc *doc,
+ int pageNumber,
+ MuOfficePageUpdateFn *updateFn,
+ void *cookie,
+ MuOfficePage **pPage)
+{
+ MuOfficePage *page;
+ MuError err = MuError_OK;
+
+ if (!doc)
+ return MuError_BadNull;
+ if (!pPage)
+ return MuError_OK;
+
+ *pPage = NULL;
+
+ ensure_doc_loaded(doc);
+
+ page = Pal_Mem_calloc(1, sizeof(*page));
+ if (page == NULL)
+ return MuError_OOM;
+
+ fz_try(doc->ctx)
+ {
+ page->doc = doc;
+ page->pageNum = pageNumber;
+ page->cookie = cookie;
+ page->updateFn = updateFn;
+ page->page = fz_load_page(doc->ctx, doc->doc, pageNumber);
+ page->next = doc->pages;
+ doc->pages = page;
+ *pPage = page;
+ }
+ fz_catch(doc->ctx)
+ {
+ Pal_Mem_free(page);
+ err = MuError_Generic;
+ }
+
+ return err;
+}
+
+/**
+ * Destroy a page object
+ *
+ * Note this does not delete or remove the page from the document.
+ * It simply destroys the page object which is merely a reference
+ * to the page.
+ *
+ * @param page the page object
+ */
+void MuOfficePage_destroy(MuOfficePage *page)
+{
+ MuOfficeDoc *doc;
+ MuOfficePage **ptr;
+
+ if (!page)
+ return;
+
+ /* Unlink page from doc */
+ doc = page->doc;
+ ptr = &doc->pages;
+ while (*ptr && *ptr != page)
+ ptr = &(*ptr)->next;
+ assert(*ptr);
+ *ptr = page->next;
+
+ fz_drop_page(doc->ctx, page->page);
+ fz_drop_display_list(doc->ctx, page->list);
+ fz_free(doc->ctx, page);
+}
+
+
+/**
+ * Get the size of a page in pixels
+ *
+ * This returns the size of the page in pixels. Pages can be rendered
+ * with a zoom factor. The returned value is the size of bitmap
+ * appropriate for rendering with a zoom of 1.0 and corresponds to
+ * 90 dpi. The returned values are not necessarily whole numbers.
+ *
+ * @param page the page object
+ * @param pWidth address for return of the width
+ * @param pHeight address for return of the height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_getSize( MuOfficePage *page,
+ float *pWidth,
+ float *pHeight)
+{
+ MuOfficeDoc *doc;
+ fz_rect rect;
+
+ if (!page)
+ return MuError_BadNull;
+ doc = page->doc;
+ if (!doc)
+ return MuError_BadNull;
+
+ fz_bound_page(doc->ctx, page->page, &rect);
+
+ /* MuPDF measures in points (72ths of an inch). This API wants
+ * 90ths of an inch, so adjust. */
+
+ if (pWidth)
+ *pWidth = 90 * (rect.x1 - rect.x0) / 72;
+ if (pHeight)
+ *pHeight = 90 * (rect.y1 - rect.y0) / 72;
+
+ return MuError_OK;
+}
+
+
+/**
+ * Return the zoom factors necessary to render at to a given
+ * size in pixels. (deprecated)
+ *
+ * @param page the page object
+ * @param width the desired width
+ * @param height the desired height
+ * @param pXZoom Address for return of zoom necessary to fit width
+ * @param pYZoom Address for return of zoom necessary to fit height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_calculateZoom( MuOfficePage *page,
+ int width,
+ int height,
+ float *pXZoom,
+ float *pYZoom)
+{
+ MuOfficeDoc *doc;
+ fz_rect rect;
+ float w, h;
+
+ if (!page)
+ return MuError_BadNull;
+ doc = page->doc;
+ if (!doc)
+ return MuError_BadNull;
+
+ fz_bound_page(doc->ctx, page->page, &rect);
+
+ /* MuPDF measures in points (72ths of an inch). This API wants
+ * 90ths of an inch, so adjust. */
+ w = 90 * (rect.x1 - rect.x0) / 72;
+ h = 90 * (rect.y1 - rect.y0) / 72;
+
+ if (pXZoom)
+ *pXZoom = width/w;
+ if (pYZoom)
+ *pYZoom = height/h;
+
+ return MuError_OK;
+}
+
+
+/**
+ * Get the size of a page in pixels for a specified zoom factor
+ * (deprecated)
+ *
+ * This returns the size of bitmap that should be used to display
+ * the entire page at the given zoom factor. A zoom of 1.0
+ * corresponds to 90 dpi.
+ *
+ * @param page the page object
+ * @param zoom the zoom factor
+ * @param pWidth address for return of the width
+ * @param pHeight address for return of the height
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_getSizeForZoom( MuOfficePage *page,
+ float zoom,
+ int *pWidth,
+ int *pHeight)
+{
+ MuOfficeDoc *doc;
+ fz_rect rect;
+ float w, h;
+
+ if (!page)
+ return MuError_BadNull;
+ doc = page->doc;
+ if (!doc)
+ return MuError_BadNull;
+
+ fz_bound_page(doc->ctx, page->page, &rect);
+
+ /* MuPDF measures in points (72ths of an inch). This API wants
+ * 90ths of an inch, so adjust. */
+ w = 90 * (rect.x1 - rect.x0) / 72;
+ h = 90 * (rect.y1 - rect.y0) / 72;
+
+ if (pWidth)
+ *pWidth = (int)(w * zoom + 0.5);
+ if (pHeight)
+ *pHeight = (int)(h * zoom + 0.5);
+
+ return MuError_OK;
+}
+
+static void render_worker(void *arg)
+{
+ MuOfficeRender *render = (MuOfficeRender *)arg;
+ MuOfficePage *page = render->page;
+ fz_context *ctx = fz_clone_context(page->doc->ctx);
+ int err = 0;
+ fz_pixmap *pixmap = NULL;
+ fz_device *dev = NULL;
+ float scalex;
+ float scaley;
+ fz_matrix matrix;
+ fz_rect page_bounds;
+
+ if (ctx == NULL)
+ return;
+
+ fz_var(pixmap);
+ fz_var(dev);
+
+ fz_try(ctx)
+ {
+ if (page->list == NULL)
+ page->list = fz_new_display_list_from_page(ctx, page->page);
+ /* Make a pixmap from the bitmap */
+ if (!render->area_valid)
+ {
+ render->area.renderArea.x = 0;
+ render->area.renderArea.y = 0;
+ render->area.renderArea.width = render->bitmap->width;
+ render->area.renderArea.height = render->bitmap->height;
+ }
+ pixmap = fz_new_pixmap_with_data(ctx,
+ fz_device_rgb(ctx),
+ render->area.renderArea.width,
+ render->area.renderArea.height,
+ 1,
+ render->bitmap->lineSkip,
+ ((unsigned char *)render->bitmap->memptr) +
+ render->bitmap->lineSkip * ((int)render->area.renderArea.x + (int)render->area.origin.x) +
+ 4 * ((int)render->area.renderArea.y + (int)render->area.origin.y));
+ /* Be a bit clever with the scaling to make sure we get
+ * integer width/heights. First calculate the target
+ * width/height. */
+ fz_bound_page(ctx, render->page->page, &page_bounds);
+ scalex = (int)(90 * render->zoom * (page_bounds.x1 - page_bounds.x0) / 72 + 0.5);
+ scaley = (int)(90 * render->zoom * (page_bounds.y1 - page_bounds.y0) / 72 + 0.5);
+ /* Now calculate the actual scale factors required */
+ scalex /= (page_bounds.x1 - page_bounds.x0);
+ scaley /= (page_bounds.y1 - page_bounds.y0);
+ /* Render the list */
+ fz_clear_pixmap_with_value(ctx, pixmap, 0xFF);
+ dev = fz_new_draw_device(ctx, fz_post_scale(fz_translate(&matrix, -page_bounds.x0, -page_bounds.y0), scalex, scaley), pixmap);
+ fz_run_display_list(ctx, page->list, dev, &fz_identity, NULL, NULL);
+ fz_close_device(ctx, dev);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_pixmap(ctx, pixmap);
+ fz_drop_device(ctx, dev);
+ }
+ fz_catch(ctx)
+ {
+ err = MuError_Generic;
+ goto fail;
+ }
+
+fail:
+ if (render->progress)
+ render->progress(render->cookie, err);
+ render->error = err;
+
+ fz_drop_context(ctx);
+}
+
+
+/**
+ * Schedule the rendering of an area of document page to
+ * an area of a bitmap.
+ *
+ * The alignment between page and bitmap is defined by specifying
+ * document's origin within the bitmap, possibly either positive or
+ * negative. A render object is returned via which the process can
+ * be monitored or terminated.
+ *
+ * The progress function is called exactly once per render in either
+ * the success or failure case.
+ *
+ * Note that, since a render object represents a running thread that
+ * needs access to the page, document, and library objects, it is important
+ * to call MuOfficeRender_destroy, not only before using or deallocating
+ * the bitmap, but also before calling MuOfficePage_destroy, etc..
+ *
+ * @param page the page to render
+ * @param zoom the zoom factor
+ * @param bitmap the bitmap
+ * @param area area to render
+ * @param progressFn the progress callback function
+ * @param cookie a pointer to pass to the callback function
+ * @param pRender Address for return of the render object
+ *
+ * @return error indication - 0 for success
+ */
+MuError MuOfficePage_render( MuOfficePage *page,
+ float zoom,
+ const MuOfficeBitmap *bitmap,
+ const MuOfficeRenderArea *area,
+ MuOfficeRenderProgressFn *progressFn,
+ void *cookie,
+ MuOfficeRender **pRender)
+{
+ MuOfficeRender *render;
+ MuOfficeDoc *doc;
+ fz_context *ctx;
+
+ if (!pRender)
+ return MuError_BadNull;
+ *pRender = NULL;
+ if (!page)
+ return MuError_BadNull;
+ doc = page->doc;
+ ctx = doc->ctx;
+
+ render = Pal_Mem_calloc(1, sizeof(*render));
+ if (render == NULL)
+ return MuError_OOM;
+
+ render->page = page;
+ render->zoom = zoom;
+ render->bitmap = bitmap;
+ if (area)
+ {
+ render->area = *area;
+ render->area_valid = 1;
+ }
+ else
+ {
+ render->area_valid = 0;
+ }
+ render->progress = progressFn;
+ render->cookie = cookie;
+
+ if (mu_create_thread(&render->thread, render_worker, render))
+ {
+ Pal_Mem_free(render);
+ return MuError_OOM;
+ }
+
+ *pRender = render;
+
+ return MuError_OK;
+}
+
+/**
+ * Destroy a render
+ *
+ * This call destroys a MuOfficeRender object, aborting any current
+ * render.
+ *
+ * This call is intended to support an app dealing with a user quickly
+ * flicking through document pages. A render may be sheduled but, before
+ * completion, be found not to be needed. In that case the bitmap will
+ * need to be reused, which requires any existing render to be aborted.
+ * The call to MuOfficeRender_destroy will cut short the render and
+ * allow the bitmap to be reused immediately.
+ *
+ * @note If an active render thread is destroyed, it will be aborted.
+ * While fast, this is not an instant operation. For maximum
+ * responsiveness, it is best to 'abort' as soon as you realise you
+ * don't need the render, and to destroy when you get the callback.
+ *
+ * @param render The render object
+ */
+void MuOfficeRender_destroy(MuOfficeRender *render)
+{
+ if (!render)
+ return;
+
+ MuOfficeRender_abort(render);
+ mu_destroy_thread(&render->thread);
+ Pal_Mem_free(render);
+}
+
+/**
+ * Abort a render
+ *
+ * This call aborts any rendering currently underway. The 'render
+ * complete' callback (if any) given when the render was created will
+ * still be called. If a render has completed, this call will have no
+ * effect.
+ *
+ * This call will not block to wait for the render thread to stop, but
+ * will cause it to stop as soon as it can in the background.
+ *
+ * @note It is important not to start any new render to the same bitmap
+ * until the callback comes in (or until waitUntilComplete returns), as
+ * otherwise you can have multiple renders drawing to the same bitmap
+ * with unpredictable consequences.
+ *
+ * @param render The render object to abort
+ */
+void MuOfficeRender_abort(MuOfficeRender *render)
+{
+ if (render)
+ render->mu_cookie.abort = 1;
+}
+
+/**
+ * Wait for a render to complete.
+ *
+ * This call will not return until rendering is complete, so on return
+ * the bitmap will contain the page image (assuming the render didn't
+ * run into an error condition) and will not be used further by any
+ * background processing. Any error during rendering will be returned
+ * from this function.
+ *
+ * This call may block the calling thread for a significant period of
+ * time. To avoid blocking, supply a progress-monitoring callback
+ * function to MuOfficePage_render.
+ *
+ * @param render The render object to destroy
+ * @return render error condition - 0 for no error.
+ */
+MuError MuOfficeRender_waitUntilComplete(MuOfficeRender *render)
+{
+ if (!render)
+ return MuError_OK;
+
+ mu_destroy_thread(&render->thread);
+
+ return render->error;
+}
diff --git a/source/tests/mu-office-test.c b/source/tests/mu-office-test.c
new file mode 100644
index 00000000..c734500a
--- /dev/null
+++ b/source/tests/mu-office-test.c
@@ -0,0 +1,288 @@
+/*
+ * mu-office-test - Simple test for Muoffice.
+ */
+
+#include "mupdf/memento.h"
+#include "mupdf/helpers/mu-office-lib.h"
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+static HANDLE loaded;
+
+/* Forward definition */
+static void save_png(const MuOfficeBitmap *bitmap, const char *filename);
+
+static void
+load_progress(void *cookie, int pages_loaded, int complete)
+{
+ assert((intptr_t)cookie == 1234);
+
+ fprintf(stderr, "load_progress: pages_loaded=%d complete=%d\n", pages_loaded, complete);
+
+ if (complete)
+ (void)ReleaseSemaphore(loaded, 1, NULL);
+}
+
+static void
+load_error(void *cookie, MuOfficeDocErrorType error)
+{
+ assert((intptr_t)cookie == 1234);
+
+ fprintf(stderr, "load_error: error=%d\n", error);
+}
+
+static void render_progress(void *cookie, MuError error)
+{
+ assert((int)cookie == 5678);
+
+ fprintf(stderr, "render_progress: error=%d\n", error);
+ (void)ReleaseSemaphore(loaded, 1, NULL);
+}
+
+static int
+test_async(MuOfficeLib *mu)
+{
+ MuOfficeDoc *doc;
+ MuError err;
+ int count;
+ MuOfficePage *page;
+ float w, h;
+ MuOfficeBitmap bitmap;
+ MuOfficeRenderArea area;
+ MuOfficeRender *render;
+
+ err = MuOfficeLib_loadDocument(mu,
+ "../MyTests/pdf_reference17.pdf",
+ load_progress,
+ load_error,
+ (void *)1234, /* Arbitrary */
+ &doc);
+
+ /* Wait for the load to complete */
+ WaitForSingleObject(loaded, INFINITE);
+
+ /* Test number of pages */
+ err = MuOfficeDoc_getNumPages(doc, &count);
+ if (err)
+ {
+ fprintf(stderr, "Failed to count pages: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+ fprintf(stderr, "%d Pages in document\n", count);
+
+ /* Get a page */
+ err = MuOfficeDoc_getPage(doc, 0, NULL, (void *)4321, &page);
+ if (err)
+ {
+ fprintf(stderr, "Failed to get page: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ /* Get size of page */
+ err = MuOfficePage_getSize(page, &w, &h);
+ if (err)
+ {
+ fprintf(stderr, "Failed to get page size: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+ fprintf(stderr, "Page size = %g x %g\n", w, h);
+
+ /* Allocate ourselves a bitmap */
+ bitmap.width = (int)(w * 1.5 + 0.5);
+ bitmap.height = (int)(h * 1.5 + 0.5);
+ bitmap.lineSkip = bitmap.width * 4;
+ bitmap.memptr = malloc(bitmap.lineSkip * bitmap.height);
+
+ /* Set the area to render the whole bitmap */
+ area.origin.x = 0;
+ area.origin.y = 0;
+ area.renderArea.x = 0;
+ area.renderArea.y = 0;
+ area.renderArea.width = (float)bitmap.width;
+ area.renderArea.height = (float)bitmap.height;
+
+ /* Render into the bitmap */
+ err = MuOfficePage_render(page, 1.5f, &bitmap, &area, render_progress, (void *)5678, &render);
+ if (err)
+ {
+ fprintf(stderr, "Page render failed: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ /* Wait for the render to complete */
+ WaitForSingleObject(loaded, INFINITE);
+
+ /* Kill the render */
+ MuOfficeRender_destroy(render);
+
+ /* Output the bitmap */
+ save_png(&bitmap, "out.png");
+ free(bitmap.memptr);
+
+ MuOfficePage_destroy(page);
+
+ MuOfficeDoc_destroy(doc);
+
+ CloseHandle(loaded);
+ loaded = NULL;
+
+ return EXIT_SUCCESS;
+}
+
+static int
+test_sync(MuOfficeLib *mu)
+{
+ MuOfficeDoc *doc;
+ MuError err;
+ int count;
+ MuOfficePage *page;
+ float w, h;
+ MuOfficeBitmap bitmap;
+ MuOfficeRenderArea area;
+ MuOfficeRender *render;
+
+ loaded = CreateSemaphore(NULL, 0, 1, NULL);
+
+ err = MuOfficeLib_loadDocument(mu,
+ "../MyTests/pdf_reference17.pdf",
+ NULL,
+ NULL,
+ NULL,
+ &doc);
+
+ /* Test number of pages */
+ err = MuOfficeDoc_getNumPages(doc, &count);
+ if (err)
+ {
+ fprintf(stderr, "Failed to count pages: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+ fprintf(stderr, "%d Pages in document\n", count);
+
+ /* Get a page */
+ err = MuOfficeDoc_getPage(doc, 1, NULL, (void *)4321, &page);
+ if (err)
+ {
+ fprintf(stderr, "Failed to get page: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ /* Get size of page */
+ err = MuOfficePage_getSize(page, &w, &h);
+ if (err)
+ {
+ fprintf(stderr, "Failed to get page size: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+ fprintf(stderr, "Page size = %g x %g\n", w, h);
+
+ /* Allocate ourselves a bitmap */
+ bitmap.width = (int)(w * 1.5 + 0.5);
+ bitmap.height = (int)(h * 1.5 + 0.5);
+ bitmap.lineSkip = bitmap.width * 4;
+ bitmap.memptr = malloc(bitmap.lineSkip * bitmap.height);
+
+ /* Set the area to render the whole bitmap */
+ area.origin.x = 0;
+ area.origin.y = 0;
+ area.renderArea.x = 0;
+ area.renderArea.y = 0;
+ area.renderArea.width = (float)bitmap.width;
+ area.renderArea.height = (float)bitmap.height;
+
+ /* Render into the bitmap */
+ err = MuOfficePage_render(page, 1.5f, &bitmap, &area, NULL, NULL, &render);
+ if (err)
+ {
+ fprintf(stderr, "Page render failed: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ err = MuOfficeRender_waitUntilComplete(render);
+ if (err)
+ {
+ fprintf(stderr, "Page render failed to complete: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ /* Kill the render */
+ MuOfficeRender_destroy(render);
+
+ /* Output the bitmap */
+ save_png(&bitmap, "out1.png");
+ free(bitmap.memptr);
+
+ MuOfficePage_destroy(page);
+
+ MuOfficeDoc_destroy(doc);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ MuOfficeLib *mu;
+ MuError err;
+ int ret;
+
+ err = MuOfficeLib_create(&mu);
+ if (err)
+ {
+ fprintf(stderr, "Failed to create lib instance: error=%d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ ret = test_async(mu);
+ if (ret)
+ return ret;
+
+ ret = test_sync(mu);
+ if (ret)
+ return ret;
+
+ MuOfficeLib_destroy(mu);
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ Code beneath here calls MuPDF directly, purely because
+ this is the easiest way to get PNG saving functionality.
+ This is not part of the test, which is why this is put
+ at the end.
+*/
+
+#include "mupdf/fitz.h"
+
+static void
+save_png(const MuOfficeBitmap *bitmap, const char *filename)
+{
+ fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
+ fz_pixmap *pix;
+
+ if (ctx == NULL)
+ {
+ fprintf(stderr, "save_png failed!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ fz_try(ctx)
+ {
+ pix = fz_new_pixmap_with_data(ctx, fz_device_rgb(ctx), bitmap->width, bitmap->height, 1, bitmap->lineSkip, bitmap->memptr);
+
+ fz_save_pixmap_as_png(ctx, pix, filename);
+ }
+ fz_always(ctx)
+ {
+ fz_drop_pixmap(ctx, pix);
+ }
+ fz_catch(ctx)
+ {
+ fprintf(stderr, "save_png failed!\n");
+ fz_drop_context(ctx);
+ exit(EXIT_FAILURE);
+ }
+
+ fz_drop_context(ctx);
+}