summaryrefslogtreecommitdiff
path: root/platform/winrt/mupdfwinrt/mudocument.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/winrt/mupdfwinrt/mudocument.cpp')
-rw-r--r--platform/winrt/mupdfwinrt/mudocument.cpp320
1 files changed, 320 insertions, 0 deletions
diff --git a/platform/winrt/mupdfwinrt/mudocument.cpp b/platform/winrt/mupdfwinrt/mudocument.cpp
new file mode 100644
index 00000000..92c24e24
--- /dev/null
+++ b/platform/winrt/mupdfwinrt/mudocument.cpp
@@ -0,0 +1,320 @@
+// mudocument.cpp
+
+/* This file contains the interface between the muctx class, which
+ implements the mupdf calls and the WinRT objects enabling calling from
+ C#, C++, Visual Basic, JavaScript applications */
+
+#include "pch.h"
+#include "mudocument.h"
+#include "status.h"
+
+using namespace mupdfwinrt;
+using namespace concurrency;
+using namespace Platform::Collections;
+
+mudocument::mudocument()
+{
+ this->mu_object.InitializeContext();
+ this->links = nullptr;
+}
+
+bool mudocument::RequiresPassword()
+{
+ return mu_object.RequiresPassword();
+}
+
+bool mudocument::ApplyPassword(String^ password)
+{
+ char* pass_char = String_to_char(password);
+ bool ok = mu_object.ApplyPassword(pass_char);
+ delete []pass_char;
+ return ok;
+}
+
+void mudocument::CleanUp()
+{
+ this->mu_object.CleanUp();
+}
+
+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::IAsyncOperation<int>^ mudocument::OpenFileAsync(StorageFile^ file)
+{
+ return create_async([this, file]()
+ {
+ String^ filetype = file->FileType;
+ const wchar_t *w = filetype->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)
+ {
+ status_t code = this->mu_object.InitializeStream(readStream, ext);
+ if (code != S_ISOK)
+ delete readStream;
+ return (int) code;
+ }
+ else
+ {
+ delete readStream;
+ return (int) E_FAILURE;
+ }
+ }
+ 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);
+}
+
+/* Do the search through the pages with an async task with progress callback */
+Windows::Foundation::IAsyncOperationWithProgress<int, double>^
+ mudocument::SearchDocumentWithProgressAsync(String^ textToFind, int dir, int start_page)
+{
+ return create_async([this, textToFind, dir, start_page](progress_reporter<double> reporter) -> int
+ {
+ int num_pages = this->GetNumPages();
+ double progress;
+ int box_count, result;
+
+ for (int i = start_page; i >= 0 && i < num_pages; i += dir)
+ {
+ box_count = this->ComputeTextSearch(textToFind, i);
+ result = i;
+ if (dir == SEARCH_FORWARD)
+ {
+ progress = 100.0 * (double) (i + 1) / (double) num_pages;
+ }
+ else
+ {
+ progress = 100.0 * (double) (num_pages - i) / (double) num_pages;
+ }
+ /* We could have it only update with certain percentage changes but
+ we are just looping over the pages here so it is not too bad */
+ reporter.report(progress);
+
+ if (is_task_cancellation_requested())
+ {
+ // Cancel the current task.
+ cancel_current_task();
+ }
+
+ if (box_count > 0)
+ {
+ return result;
+ }
+ if (is_task_cancellation_requested())
+ {
+ }
+ }
+ reporter.report(100.0);
+ /* Todo no matches found alert */
+ if (box_count == 0)
+ return TEXT_NOT_FOUND;
+ else
+ return result;
+ });
+}
+
+/* Pack the page into a bmp stream */
+Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
+ mudocument::RenderPageAsync(int page_num, int width, int height, bool use_dlist)
+{
+ return create_async([this, width, height, page_num, use_dlist](cancellation_token ct) -> 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 */
+ status_t code = mu_object.RenderPage(page_num, width, height, &(bmp_data[0]),
+ use_dlist);
+ if (code != S_ISOK)
+ {
+ 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);
+ }
+ delete []text_char;
+ return num_items;
+}
+
+/* Return number of hits found on most recent page */
+int mudocument::TextSearchCount(void)
+{
+ if (this->textsearch != nullptr)
+ return this->textsearch->Size;
+ else
+ return 0;
+}
+
+/* Returns the kth item for a page after a text search query */
+Links^ mudocument::GetTextSearch(int k)
+{
+ if (k >= this->textsearch->Size)
+ return nullptr;
+ return this->textsearch->GetAt(k);
+}
+
+int mudocument::ComputeContents()
+{
+ 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_content content_smart_ptr_vec(new std::vector<sh_content>());
+
+ int has_content = mu_object.GetContents(content_smart_ptr_vec);
+
+ if (!has_content)
+ return 0;
+ /* Pack into winRT type*/
+ this->contents = ref new Platform::Collections::Vector<ContentItem^>();
+ int num_items = content_smart_ptr_vec->size();
+
+ for (int k = 0; k < num_items; k++)
+ {
+ auto new_content = ref new ContentItem();
+ sh_content muctx_content = content_smart_ptr_vec->at(k);
+ new_content->Page = muctx_content->page;
+ new_content->StringMargin = muctx_content->string_margin;
+ new_content->StringOrig = muctx_content->string_orig;
+ this->contents->Append(new_content);
+ }
+ return num_items;
+}
+
+ContentItem^ mudocument::GetContent(int k)
+{
+ if (k >= this->contents->Size)
+ return nullptr;
+ return this->contents->GetAt(k);
+}
+
+String^ mudocument::ComputeHTML(int page_num)
+{
+ std::lock_guard<std::mutex> lock(mutex_lock);
+ return mu_object.GetHTML(page_num);
+}