diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2013-05-04 22:59:31 -0700 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-05-16 19:25:44 +0100 |
commit | ced8337a902cfb9988d014c099b90b2b66212825 (patch) | |
tree | c91a41d504b4cbddec169a2e5e4a2a5031863ad4 /winrt/mupdfwinrt | |
parent | 4bbdac7510e0a02f86fd00629a8b344d85404528 (diff) | |
download | mupdf-ced8337a902cfb9988d014c099b90b2b66212825.tar.xz |
Major changes in the entire design.
Initial commit of this and it has several issues that have to be worked through. Lots of
broken stuff but I needed to get it in place.
Added 2 new classes. One is muctx which contains all the interfacing to mupdf and uses
standard c++ types. The other is mudocument which interfaces between muctx and the WinRT
world. It passes WinRT objects to and from applications which can be written in C++, C#,
Visual Basic, Javascript etc. mudocument and muctx will reside in a winRT DLL. The
Viewer application (c++ version) is now in mupdf_cpp project and now has a flip view
structure that includes a scroll viewer which has data binding to a collection. This
enables much easier zooming and updating, however I am still trying how to bind the
canvas elements that contain the text search or link information.
Diffstat (limited to 'winrt/mupdfwinrt')
-rw-r--r-- | winrt/mupdfwinrt/Links.cpp | 11 | ||||
-rw-r--r-- | winrt/mupdfwinrt/Links.h | 72 | ||||
-rw-r--r-- | winrt/mupdfwinrt/muctx.cpp | 404 | ||||
-rw-r--r-- | winrt/mupdfwinrt/muctx.h | 81 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mudocument.cpp | 212 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mudocument.h | 40 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mupdfwinrt.vcxproj | 230 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters | 22 | ||||
-rw-r--r-- | winrt/mupdfwinrt/pch.cpp | 6 | ||||
-rw-r--r-- | winrt/mupdfwinrt/pch.h | 6 | ||||
-rw-r--r-- | winrt/mupdfwinrt/utils.h | 8 |
11 files changed, 1092 insertions, 0 deletions
diff --git a/winrt/mupdfwinrt/Links.cpp b/winrt/mupdfwinrt/Links.cpp new file mode 100644 index 00000000..eb8dfac7 --- /dev/null +++ b/winrt/mupdfwinrt/Links.cpp @@ -0,0 +1,11 @@ +#include "pch.h" +#include "Links.h" + +using namespace mupdfwinrt; + +Links::Links(void) +{ + this->uri = nullptr; + this->page_num = -1; + this->type = NOT_SET; +} diff --git a/winrt/mupdfwinrt/Links.h b/winrt/mupdfwinrt/Links.h new file mode 100644 index 00000000..64072e35 --- /dev/null +++ b/winrt/mupdfwinrt/Links.h @@ -0,0 +1,72 @@ +#pragma once + +#include "utils.h" + +using namespace Windows::Foundation; + +namespace mupdfwinrt +{ + public ref class Links sealed + { + private: + int type; + Point upper_left; + Point lower_right; + Windows::Foundation::Uri ^uri; + int page_num; + public: + Links(void); + + property int Type + { + int get() { return (type); } + void set(int value) + { + if (value > NOT_SET) + { + throw ref new Platform::InvalidArgumentException(); + } + type = value; + } + } + + property Point UpperLeft + { + Point get() { return upper_left; } + void set(Point value) + { + upper_left = value; + } + } + + property Point LowerRight + { + Point get() { return lower_right; } + void set(Point value) + { + lower_right = value; + } + } + + property int PageNum + { + int get() { return page_num; } + void set(int value) + { + page_num = value; + } + } + + property Windows::Foundation::Uri^ Uri + { + Windows::Foundation::Uri^ get() { return uri; } + void set(Windows::Foundation::Uri^ value) + { + uri = value; + } + } + }; +} + + + diff --git a/winrt/mupdfwinrt/muctx.cpp b/winrt/mupdfwinrt/muctx.cpp new file mode 100644 index 00000000..fcdac960 --- /dev/null +++ b/winrt/mupdfwinrt/muctx.cpp @@ -0,0 +1,404 @@ +#pragma once + +#include "pch.h" +#include "muctx.h" +#include "Links.h" + +/* This class interfaces to mupdf API with minimal windows objects (other than + the file streaming stuff) */ + +/* File streaming set up for mupdf */ + +/* win_read_file etc. Reading of windows managed stream. This is not ideal as I have + to read into a managed buffer and then transfer to the actual buffer I want. I + would like a more direct approach. Alternate approach is to push this off + outside the winrt and read from a memory buffer. */ +static int win_read_file(fz_stream *stm, unsigned char *buf, int len) +{ + void *temp = stm->state; + win_stream_struct *stream = reinterpret_cast <win_stream_struct*> (temp); + IRandomAccessStream^ Stream = stream->stream; + unsigned long long curr_pos = Stream->Position; + unsigned long long length = Stream->Size; + DataReader^ local_reader = ref new DataReader(Stream); + DataReaderLoadOperation^ result = local_reader->LoadAsync(len); + + /* Block on the Async call */ + while(result->Status != AsyncStatus::Completed) { + + } + + result->GetResults(); + int curr_len2 = local_reader->UnconsumedBufferLength; + if (curr_len2 < len) + len = curr_len2; + + Platform::Array<unsigned char>^ arrByte = ref new Platform::Array<unsigned char>(len); + local_reader->ReadBytes(arrByte); + + memcpy(buf, arrByte->Data, len); + local_reader->DetachStream(); + + return len; +} + +static void win_seek_file(fz_stream *stm, int offset, int whence) +{ + void *temp = stm->state; + win_stream_struct *stream = reinterpret_cast <win_stream_struct*> (temp); + IRandomAccessStream^ Stream = stream->stream; + unsigned long long curr_pos = Stream->Position; + unsigned long long length = Stream->Size; + unsigned long long n; + + if (whence == SEEK_END) + { + n = length + offset; + } + else if (whence == SEEK_CUR) + { + n = curr_pos + offset; + } + else if (whence == SEEK_SET) + { + n = offset; + } + Stream->Seek(n); + curr_pos = Stream->Position; + stm->pos = n; + stm->rp = stm->bp; + stm->wp = stm->bp; +} + +static void win_close_file(fz_context *ctx, void *state) +{ + DataReader^ dataReader = reinterpret_cast <DataReader^> (state); + + delete dataReader; +} + +/* mutext functions see mupdf readme for details */ +static void lock_mutex(void *user, int lock) +{ + EnterCriticalSection((LPCRITICAL_SECTION)user); +} + +static void unlock_mutex(void *user, int lock) +{ + LeaveCriticalSection((LPCRITICAL_SECTION)user); +} + +/* Set up the context, mutex and cookie */ +HRESULT muctx::InitializeContext() +{ + /* Get the mutex set up */ + InitializeCriticalSectionEx(&mu_criticalsec, 0, 0); + mu_locks.user = &mu_criticalsec; + mu_locks.lock = lock_mutex; + mu_locks.unlock = unlock_mutex; + + /* Allocate the context */ + this->mu_ctx = fz_new_context(NULL, &mu_locks, FZ_STORE_DEFAULT); + if (this->mu_ctx == NULL) + { + return E_OUTOFMEMORY; + } + else + { + /* If we are fine, allocate the cookie for progress etc. */ + this->mu_cookie = (fz_cookie*)malloc(sizeof(fz_cookie)); + if (this->mu_cookie == NULL) { + fz_free_context(this->mu_ctx); + return E_OUTOFMEMORY; + } + else + return S_OK; + } +} + +/* Initializer */ +muctx::muctx(void) +{ + this->mu_cookie = NULL; + this->mu_ctx = NULL; + this->mu_doc = NULL; + this->mu_outline = NULL; + this->mu_stream = NULL; +} + +/* Destructor */ +muctx::~muctx(void) +{ + free(this->mu_cookie); + if (mu_outline != NULL) + fz_free_outline(mu_ctx, mu_outline); + if (mu_doc != NULL) + fz_close_document(mu_doc); + if (mu_ctx != NULL) + fz_free_context(mu_ctx); + + this->mu_cookie = NULL; + this->mu_ctx = NULL; + this->mu_doc = NULL; + this->mu_outline = NULL; + this->mu_stream = NULL; +} + +/* Set up the stream access */ +HRESULT muctx::InitializeStream(IRandomAccessStream^ readStream, char *ext) +{ + win_stream.stream = readStream; + this->mu_stream = fz_new_stream(mu_ctx, 0, win_read_file, win_close_file); + this->mu_stream->seek = win_seek_file; + this->mu_stream->state = reinterpret_cast <void*> (&win_stream); + + /* Now lets see if we can open the file */ + mu_doc = fz_open_document_with_stream(mu_ctx, ext, this->mu_stream); + + if (mu_doc == NULL) + return E_FAIL; + else + return S_OK; +} + +/* Return the documents page count */ +int muctx::GetPageCount() +{ + if (this->mu_doc == NULL) + return -1; + else + return this->mu_doc->count_pages(this->mu_doc); +} + +/* Get page size */ +Point muctx::MeasurePage(int page_num) +{ + Point pageSize; + fz_rect rect; + fz_page *page; + fz_rect *bounds; + + page = fz_load_page(mu_doc, page_num); + bounds = fz_bound_page(mu_doc, page, &rect); + pageSize.X = bounds->x1 - bounds->x0; + pageSize.Y = bounds->y1 - bounds->y0; + + return pageSize; +} + +/* Get page size */ +Point muctx::MeasurePage(fz_page *page) +{ + Point pageSize; + fz_rect rect; + fz_rect *bounds; + + bounds = fz_bound_page(mu_doc, page, &rect); + pageSize.X = bounds->x1 - bounds->x0; + pageSize.Y = bounds->y1 - bounds->y0; + + return pageSize; +} + +int muctx::GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec) +{ + fz_page *page; + fz_text_sheet *sheet; + fz_device *dev; + fz_context *ctx_clone; + fz_text_page *text; + int k; + int hit_count = 0; + + if (mu_cookie->abort == 1) + return hit_count; + + ctx_clone = fz_clone_context(mu_ctx); + + fz_var(page); + fz_var(sheet); + fz_var(dev); + fz_try(ctx_clone) + { + page = fz_load_page(mu_doc, page_num); + sheet = fz_new_text_sheet(ctx_clone); + text = fz_new_text_page(ctx_clone, &fz_empty_rect); + dev = fz_new_text_device(ctx_clone, sheet, text); + fz_run_page(mu_doc, page, dev, &fz_identity, NULL); + fz_free_device(dev); /* Why does this need to be done here? Seems odd */ + dev = NULL; + hit_count = fz_search_text_page(ctx_clone, text, needle, mu_hit_bbox, nelem(mu_hit_bbox)); + + for (k = 0; k < hit_count; k++) + { + sh_text text_search(new text_search_t()); + text_search->upper_left.X = mu_hit_bbox[k].x0; + text_search->upper_left.Y = mu_hit_bbox[k].y0; + text_search->lower_right.X = mu_hit_bbox[k].x1; + text_search->lower_right.Y = mu_hit_bbox[k].x1; + texts_vec->push_back(text_search); + } + } + fz_always(ctx_clone) + { + if (page != NULL) + { + fz_free_page(mu_doc, page); + } + if (dev != NULL) + { + fz_free_device(dev); + } + if (sheet != NULL) + { + fz_free_text_sheet(ctx_clone, sheet); + } + } + fz_catch(ctx_clone) + { + return E_FAIL; + } + return hit_count; +} + + + +/* Get the links and pack into a smart pointer structure */ +int muctx::GetLinks(int page_num, sh_vector_link links_vec) +{ + fz_page *page; + fz_link *links; + fz_context *ctx_clone; + int k = 0; + int num_links = 0; + + if (mu_cookie->abort == 1) + return num_links; + + ctx_clone = fz_clone_context(mu_ctx); + + fz_var(page); + fz_var(links); + fz_try(ctx_clone) + { + page = fz_load_page(mu_doc, page_num); + links = fz_load_links(mu_doc, page); + + fz_link *curr_link = links; + if (curr_link == NULL) + return num_links; + + /* Get our smart pointer structure filled */ + while (curr_link != NULL) + { + fz_rect curr_rect = curr_link->rect; + sh_link link(new document_link_t()); + + link->upper_left.X = curr_rect.x0; + link->upper_left.Y = curr_rect.y0; + link->lower_right.X = curr_rect.x1; + link->lower_right.Y = curr_rect.x1; + + switch (curr_link->dest.kind) + { + case FZ_LINK_GOTO: + + link->type = LINK_GOTO; + link->page_num = curr_link->dest.ld.gotor.page; + break; + + case FZ_LINK_URI: + { + int lenstr = strlen(curr_link->dest.ld.uri.uri); + std::unique_ptr<char[]> uri(new char[lenstr + 1]); + strcpy_s(uri.get(), lenstr + 1, curr_link->dest.ld.uri.uri); + link->uri.swap(uri); + link->type = LINK_URI; + break; + } + + default: + link->type = NOT_SET; + + } + links_vec->push_back(link); + curr_link = curr_link->next; + num_links += 1; + } + } + fz_always(ctx_clone) + { + if (page != NULL) + { + fz_free_page(mu_doc, page); + } + if (links != NULL) + { + fz_drop_link(ctx_clone, links); + } + } + fz_catch(ctx_clone) + { + return E_FAIL; + } + return num_links; +} + +/* Render page_num to size width by height into bmp_data buffer */ +HRESULT muctx::RenderPage(int page_num, int width, int height, + unsigned char *bmp_data) +{ + fz_device *dev; + fz_pixmap *pix; + fz_page *page; + fz_matrix ctm, *pctm = &ctm; + Point page_size; + fz_context *ctx_clone; + + if (mu_cookie->abort == 1) + return S_OK; + + ctx_clone = fz_clone_context(mu_ctx); + + fz_var(dev); + fz_var(pix); + fz_var(page); + fz_try(ctx_clone) + { + page = fz_load_page(mu_doc, page_num); + page_size = MeasurePage(page); + + /* Figure out scale factors so that we get the desired size */ + pctm = fz_scale(pctm, (float) width / page_size.X, (float) height / page_size.Y); + /* Flip on Y */ + ctm.f = height; + ctm.d = -ctm.d; + pix = fz_new_pixmap_with_data(ctx_clone, fz_device_bgr, width, height, bmp_data); + fz_clear_pixmap_with_value(ctx_clone, pix, 255); + dev = fz_new_draw_device(ctx_clone, pix); + fz_run_page(mu_doc, page, dev, pctm, NULL); + } + fz_always(ctx_clone) + { + if (dev != NULL) + { + fz_free_device(dev); + } + if (pix != NULL) + { + fz_drop_pixmap(ctx_clone, pix); + } + if (page != NULL) + { + fz_free_page(mu_doc, page); + } + } + fz_catch(ctx_clone) + { + return E_FAIL; + } + + fz_free_context(ctx_clone); + + return S_OK; +} diff --git a/winrt/mupdfwinrt/muctx.h b/winrt/mupdfwinrt/muctx.h new file mode 100644 index 00000000..61aec5a4 --- /dev/null +++ b/winrt/mupdfwinrt/muctx.h @@ -0,0 +1,81 @@ +#pragma once + +#include <memory> +#include <functional> +#include <vector> +#include "utils.h" + +#include <windows.h> +#include <Winerror.h> +#include <mutex> + +extern "C" { + #include "fitz.h" + #include "fitz-internal.h" + #include "muxps.h" + #include "mupdf.h" +} + +#define MAX_SEARCH 500 + +using namespace Windows::Foundation; /* For Point */ + +typedef struct document_link_s +{ + link_t type; + Point upper_left; + Point lower_right; + std::unique_ptr<char[]> uri; + int page_num; +} document_link_t; + +#define sh_link std::shared_ptr<document_link_t> +#define sh_vector_link std::shared_ptr<std::vector<sh_link>> + +typedef struct text_search_s +{ + Point upper_left; + Point lower_right; +} text_search_t; + +#define sh_text std::shared_ptr<text_search_t> +#define sh_vector_text std::shared_ptr<std::vector<sh_text>> + +/* Needed for file handling */ +using namespace Windows::Storage::Streams; +using namespace Windows::Foundation; + +typedef struct win_stream_struct_s +{ + IRandomAccessStream^ stream; +} win_stream_struct; + +class muctx +{ +private: + CRITICAL_SECTION mu_criticalsec; + win_stream_struct win_stream; + fz_locks_context mu_locks; + fz_context *mu_ctx; + fz_document *mu_doc; + fz_outline *mu_outline; + fz_rect mu_hit_bbox[MAX_SEARCH]; + fz_cookie *mu_cookie; + fz_stream *mu_stream; + +public: + muctx(void); + ~muctx(void); + HRESULT InitializeStream(IRandomAccessStream^ readStream, char *ext); + int GetPageCount(); + HRESULT InitializeContext(); + HRESULT RenderPage(int page_num, int width, int height, unsigned char *bmp_data); + Point MeasurePage(int page_num); + Point MeasurePage(fz_page *page); + int GetLinks(int page_num, sh_vector_link links_vec); + int GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec); +}; + + + + diff --git a/winrt/mupdfwinrt/mudocument.cpp b/winrt/mupdfwinrt/mudocument.cpp new file mode 100644 index 00000000..cf02083d --- /dev/null +++ b/winrt/mupdfwinrt/mudocument.cpp @@ -0,0 +1,212 @@ +// mudocument.cpp +#include "pch.h" +#include "mudocument.h" + +using namespace mupdfwinrt; +using namespace concurrency; +using namespace Platform::Collections; + +/* Window string hurdles.... */ +static String^ char_to_String(char *char_in) +{ + size_t size = MultiByteToWideChar(CP_UTF8, 0, char_in, -1, NULL, 0); + wchar_t *pw; + pw = new wchar_t[size]; + if (!pw) + { + delete []pw; + return nullptr; + } + MultiByteToWideChar(CP_UTF8, 0, char_in, -1, pw, size ); + String^ str_out = ref new String(pw); + delete []pw; + return str_out; +} + +static char* String_to_char(String^ text) +{ + const wchar_t *w = text->Data(); + int cb = WideCharToMultiByte(CP_UTF8, 0, text->Data(), -1, nullptr, 0, nullptr, nullptr); + char* charout = new char[cb]; + WideCharToMultiByte(CP_UTF8, 0, text->Data() ,-1 ,charout ,cb ,nullptr, nullptr); + return charout; +} + +mudocument::mudocument() +{ + this->mu_object.InitializeContext(); + this->links = nullptr; +} + +int mudocument::GetNumPages() +{ + return this->mu_object.GetPageCount(); +} + +Point mudocument::GetPageSize(int page_num) +{ + std::lock_guard<std::mutex> lock(mutex_lock); + return this->mu_object.MeasurePage(page_num); +} + +Windows::Foundation::IAsyncAction^ mudocument::OpenFile(StorageFile^ file) +{ + return create_async([this, file]() + { + String^ path = file->Path; + const wchar_t *w = path->Data(); + int cb = WideCharToMultiByte(CP_UTF8, 0, w, -1, nullptr, 0, nullptr, nullptr); + char* name = new char[cb]; + + WideCharToMultiByte(CP_UTF8, 0, w ,-1 ,name ,cb ,nullptr, nullptr); + char *ext = strrchr(name, '.'); + + auto t = create_task(file->OpenAsync(FileAccessMode::Read)); + + return t.then([this, file, ext](task<IRandomAccessStream^> task) + { + try + { + IRandomAccessStream^ readStream = task.get(); + UINT64 const size = readStream->Size; + + if (size <= MAXUINT32) + { + HRESULT code = this->mu_object.InitializeStream(readStream, ext); + return; + } + else + { + delete readStream; + return; + } + } + catch(COMException^ ex) { + /* Need to do something useful here */ + throw ex; + } + }); + }); +} + +/* Header info for bmp stream so that we can use the image brush */ +static void Prepare_bmp(int width, int height, DataWriter ^dw) +{ + int row_size = width * 4; + int bmp_size = row_size * height + 54; + + dw->WriteString("BM"); + dw->ByteOrder = ByteOrder::LittleEndian; + dw->WriteInt32(bmp_size); + dw->WriteInt16(0); + dw->WriteInt16(0); + dw->WriteInt32(54); + dw->WriteInt32(40); + dw->WriteInt32(width); + dw->WriteInt32(height); + dw->WriteInt16(1); + dw->WriteInt16(32); + dw->WriteInt32(0); + dw->WriteInt32(row_size * height); + dw->WriteInt32(2835); + dw->WriteInt32(2835); + dw->WriteInt32(0); + dw->WriteInt32(0); +} + +/* Pack the page into a bmp stream so that we can use it with an image brush */ +Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^ + mudocument::RenderPage(int page_num, int width, int height) +{ + return create_async([this, width, height, page_num]() -> InMemoryRandomAccessStream^ + { + /* Allocate space for bmp */ + Array<unsigned char>^ bmp_data = ref new Array<unsigned char>(height * 4 * width); + /* Set up the memory stream */ + InMemoryRandomAccessStream ^ras = ref new InMemoryRandomAccessStream(); + DataWriter ^dw = ref new DataWriter(ras->GetOutputStreamAt(0)); + + /* Go ahead and write our header data into the memory stream */ + Prepare_bmp(width, height, dw); + + std::lock_guard<std::mutex> lock(mutex_lock); + + /* Get raster bitmap stream */ + HRESULT code = mu_object.RenderPage(page_num, width, height, &(bmp_data[0])); + if (code != S_OK) + { + throw ref new FailureException("Page Rendering Failed"); + } + /* Now the data into the memory stream */ + dw->WriteBytes(bmp_data); + DataWriterStoreOperation^ result = dw->StoreAsync(); + /* Block on this Async call? */ + while(result->Status != AsyncStatus::Completed) { + } + /* Return raster stream */ + return ras; + }); +} + +int mudocument::ComputeLinks(int page_num) +{ + std::lock_guard<std::mutex> lock(mutex_lock); + /* We get back a standard smart pointer from muctx interface and go to WinRT + type here */ + sh_vector_link link_smart_ptr_vec(new std::vector<sh_link>()); + int num_items = mu_object.GetLinks(page_num, link_smart_ptr_vec); + if (num_items == 0) + return 0; + /* Pack into winRT type*/ + this->links = ref new Platform::Collections::Vector<Links^>(); + for (int k = 0; k < num_items; k++) + { + auto new_link = ref new Links(); + sh_link muctx_link = link_smart_ptr_vec->at(k); + new_link->LowerRight = muctx_link->lower_right; + new_link->UpperLeft = muctx_link->upper_left; + new_link->PageNum = muctx_link->page_num; + new_link->Type = muctx_link->type; + if (new_link->Type == LINK_URI) + { + String^ str = char_to_String(muctx_link->uri.get()); + // The URI to launch + new_link->Uri = ref new Windows::Foundation::Uri(str); + } + this->links->Append(new_link); + } + return num_items; +} + +Links^ mudocument::GetLink(int k) +{ + if (k >= this->links->Size) + return nullptr; + return this->links->GetAt(k); +} + +int mudocument::ComputeTextSearch(String^ text, int page_num) +{ + std::lock_guard<std::mutex> lock(mutex_lock); + /* We get back a standard smart pointer from muctx interface and go to WinRT + type here */ + char* text_char = String_to_char(text); + sh_vector_text text_smart_ptr_vec(new std::vector<sh_text>()); + + int num_items = mu_object.GetTextSearch(page_num, text_char, text_smart_ptr_vec); + if (num_items == 0) + return 0; + /* Pack into winRT type*/ + this->textsearch = ref new Platform::Collections::Vector<Links^>(); + for (int k = 0; k < num_items; k++) + { + auto new_link = ref new Links(); + sh_text muctx_text = text_smart_ptr_vec->at(k); + new_link->LowerRight = muctx_text->lower_right; + new_link->UpperLeft = muctx_text->upper_left; + new_link->Type = TEXTBOX; + this->textsearch->Append(new_link); + } + return num_items; +} + diff --git a/winrt/mupdfwinrt/mudocument.h b/winrt/mupdfwinrt/mudocument.h new file mode 100644 index 00000000..b315a18f --- /dev/null +++ b/winrt/mupdfwinrt/mudocument.h @@ -0,0 +1,40 @@ +#pragma once + +/* This file contains the WinRT API interface between the muctx class which + implements the mupdf calls and the WinRT objects enabling calling from + C#, C++, Visual Basic, JavaScript applications */ + +#include "muctx.h" +#include "Links.h" +#include "ppltasks.h" +#include <winnt.h> +#include <collection.h> + +using namespace Windows::Storage; +using namespace Platform; +using namespace Concurrency; +using namespace Platform::Collections; + +namespace mupdfwinrt +{ + public ref class mudocument sealed + { + + private: + muctx mu_object; + std::mutex mutex_lock; + Platform::Collections::Vector<Links^>^ links; + Platform::Collections::Vector<Links^>^ textsearch; + public: + mudocument(); + Windows::Foundation::IAsyncAction^ OpenFile(StorageFile^ file); + int GetNumPages(); + Point GetPageSize(int page_num); + Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^ + RenderPage(int page_num, int width, int height); + int ComputeLinks(int page_num); + Links^ GetLink(int k); + int ComputeTextSearch(String^ text, int page_num); + + }; +}
\ No newline at end of file diff --git a/winrt/mupdfwinrt/mupdfwinrt.vcxproj b/winrt/mupdfwinrt/mupdfwinrt.vcxproj new file mode 100644 index 00000000..5e8892be --- /dev/null +++ b/winrt/mupdfwinrt/mupdfwinrt.vcxproj @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{9e6ab41d-09a7-45a6-a53b-1e4bf3ac5b33}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <ProjectName>mupdfwinrt</ProjectName> + <RootNamespace>mupdfwinrt</RootNamespace> + <DefaultLanguage>en-US</DefaultLanguage> + <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + <AppContainerApplication>true</AppContainerApplication> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <GenerateManifest>false</GenerateManifest> + <OutDir>..\$(Platform)\$(Configuration)\</OutDir> + <IntDir>..\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <GenerateManifest>false</GenerateManifest> + <OutDir>$(Platform)\$(Configuration)\</OutDir> + <IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <GenerateManifest>false</GenerateManifest> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + <AdditionalIncludeDirectories>../../xps/;../../pdf/;../../fitz/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;../$(Platform)/$(Configuration)/libmupdf_winRT.lib;../$(Platform)/$(Configuration)/libthirdparty_winRT.lib;../$(Platform)/$(Configuration)/libmupdf-nov8_winRT.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + <AdditionalIncludeDirectories>../../xps/;../../pdf/;../../fitz/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;../../$(Platform)/$(Configuration)/libmupdf_winRT.lib;../../$(Platform)/$(Configuration)/libthirdparty_winRT.lib;../../$(Platform)/$(Configuration)/libmupdf-nov8_winRT.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PreprocessorDefinitions>_WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> + <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies> + <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="Links.h" /> + <ClInclude Include="muctx.h" /> + <ClInclude Include="pch.h" /> + <ClInclude Include="mudocument.h" /> + <ClInclude Include="utils.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Links.cpp" /> + <ClCompile Include="muctx.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="mudocument.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters b/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters new file mode 100644 index 00000000..c00d9539 --- /dev/null +++ b/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Resources"> + <UniqueIdentifier>16ec6626-1276-4cf1-b7af-8d28de2c8f75</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp" /> + <ClCompile Include="mudocument.cpp" /> + <ClCompile Include="muctx.cpp" /> + <ClCompile Include="Links.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h" /> + <ClInclude Include="mudocument.h" /> + <ClInclude Include="muctx.h" /> + <ClInclude Include="Links.h" /> + <ClInclude Include="utils.h" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/winrt/mupdfwinrt/pch.cpp b/winrt/mupdfwinrt/pch.cpp new file mode 100644 index 00000000..01484ff5 --- /dev/null +++ b/winrt/mupdfwinrt/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/winrt/mupdfwinrt/pch.h b/winrt/mupdfwinrt/pch.h new file mode 100644 index 00000000..f815ac97 --- /dev/null +++ b/winrt/mupdfwinrt/pch.h @@ -0,0 +1,6 @@ +// +// pch.h +// Header for standard system include files. +// + +#pragma once diff --git a/winrt/mupdfwinrt/utils.h b/winrt/mupdfwinrt/utils.h new file mode 100644 index 00000000..7485ee47 --- /dev/null +++ b/winrt/mupdfwinrt/utils.h @@ -0,0 +1,8 @@ +#pragma once + +typedef enum { + LINK_GOTO = 0, + LINK_URI, + TEXTBOX, /* Do double duty with this class */ + NOT_SET, +} link_t;
\ No newline at end of file |