From 4a7e2298fff3a1972fda5c537a8c5e7c6d8f8292 Mon Sep 17 00:00:00 2001 From: Michael Vrhel Date: Thu, 16 May 2013 07:28:26 -0700 Subject: Addition of progress bar code with cancel during text search. Also place holders for password support and initial work towards keyboard based zooming. --- winrt/README.txt | 34 +++++++-- winrt/mupdf_cpp/MainPage.xaml | 17 ++++- winrt/mupdf_cpp/MainPage.xaml.cpp | 153 +++++++++++++++++++++++--------------- winrt/mupdf_cpp/MainPage.xaml.h | 11 +-- winrt/mupdfwinrt/muctx.cpp | 12 +++ winrt/mupdfwinrt/muctx.h | 2 + winrt/mupdfwinrt/mudocument.cpp | 74 +++++++++++++++++- winrt/mupdfwinrt/mudocument.h | 15 +++- 8 files changed, 237 insertions(+), 81 deletions(-) (limited to 'winrt') diff --git a/winrt/README.txt b/winrt/README.txt index 1ae59d2f..4beaefbf 100644 --- a/winrt/README.txt +++ b/winrt/README.txt @@ -1,14 +1,38 @@ This MSVC project needs the thirdparty sources to be in place. -Current Issues: +mupdf_cpp: + +This is the c++ viewer code, which creates and handles the UI. + +mupdfwinrt: + +This defines the WinRT interface to mupdf. +There are two primary classes, mudocument and muctx. +The viewer code should create a +mudocument type and make use of the methods in +this winRT class. The mupdocument class is a winRT +class and the methods should be callable from +C++, C#, Javascript etc. -Text search destroys the link canvas +The muctx class interfaces to the mupdf API calls +and pretty much uses standard c++ methods with +the exception of the Windows types String and Point. + +mupdfwinrt lib is linked statically to the viewer +code, but this could be set up as a DLL if desired. + +The libraries generated, libmupdf_winRT, libmupdf-nov8_winRT +and libthridparty_winRT are essentially the same as those +in the win32 project, however they are needed here for +building with VS 2012 ARM target. + +Current Issues: -Small horizontal sizes squash buttons together +Space/Tab needs to be reworked in files -Small horizontal resize reflow back to flipview has issues +State needs to be saved during suspension -Still needs error checking +Still needs additional error checking Needs progress bar during text search diff --git a/winrt/mupdf_cpp/MainPage.xaml b/winrt/mupdf_cpp/MainPage.xaml index 54226eac..184b3668 100644 --- a/winrt/mupdf_cpp/MainPage.xaml +++ b/winrt/mupdf_cpp/MainPage.xaml @@ -59,8 +59,6 @@ - - @@ -240,6 +238,21 @@ ScrollViewer.VerticalScrollMode="Enabled" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.ZoomMode="Enabled"/> + + + + + + + + + + + diff --git a/winrt/mupdf_cpp/MainPage.xaml.cpp b/winrt/mupdf_cpp/MainPage.xaml.cpp index 76c0ecf3..5b8dfeab 100644 --- a/winrt/mupdf_cpp/MainPage.xaml.cpp +++ b/winrt/mupdf_cpp/MainPage.xaml.cpp @@ -6,24 +6,21 @@ #include "pch.h" #include "MainPage.xaml.h" -#define LOOK_AHEAD 1 /* A +/- count on the pages to pre-render */ +#define LOOK_AHEAD 0 /* A +/- count on the pages to pre-render */ #define THUMB_PREADD 10 #define MIN_SCALE 0.5 -#define MAX_SCALE 4 -#define MARGIN_BUFF 400 -#define MAX_SEARCH 500 + #define SCALE_THUMB 0.1 #define BLANK_WIDTH 17 #define BLANK_HEIGHT 22 -static float screenScale = 1; +#define KEY_PLUS 0xbb +#define KEY_MINUS 0xbd -int linkPage[MAX_SEARCH]; -char *linkUrl[MAX_SEARCH]; +static float screenScale = 1; using namespace mupdf_cpp; - using namespace Windows::Foundation; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; @@ -405,6 +402,7 @@ void mupdf_cpp::MainPage::CleanUp() m_ren_status = REN_AVAILABLE; m_links_on = false; m_rectlist_page = -1; + m_Progress = 0.0; this->xaml_PageSlider->Minimum = m_slider_min; this->xaml_PageSlider->Maximum = m_slider_max; @@ -433,7 +431,7 @@ void mupdf_cpp::MainPage::RenderThumbs() Point ras_size = ComputePageSize(spatial_info_local, k); bool done = false; DWORD thread1_id = GetCurrentThreadId(); - auto task2 = create_task(mu_doc->RenderPage(k, ras_size.X, ras_size.Y)); + auto task2 = create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y)); task2.then([this, k, thumbnails, ras_size](InMemoryRandomAccessStream^ ras) { @@ -492,6 +490,7 @@ void mupdf_cpp::MainPage::RenderThumbs() } this->m_ren_status = REN_AVAILABLE; }, task_continuation_context::use_current()); + } void mupdf_cpp::MainPage::OpenDocumentPrep(StorageFile^ file) @@ -544,13 +543,14 @@ void mupdf_cpp::MainPage::OpenDocument(StorageFile^ file) this->SetFlipView(); /* Open document and when open, push on */ - auto open_task = create_task(mu_doc->OpenFile(file)); + auto open_task = create_task(mu_doc->OpenFileAsync(file)); open_task.then([this] { assert(IsMainThread()); m_num_pages = mu_doc->GetNumPages(); + if ((m_currpage) >= m_num_pages) { m_currpage = m_num_pages - 1; @@ -559,7 +559,6 @@ void mupdf_cpp::MainPage::OpenDocument(StorageFile^ file) { m_currpage = 0; } - /* Initialize all the flipvew items with blanks and the thumbnails. */ for (int k = 0; k < m_num_pages; k++) { @@ -592,7 +591,7 @@ void mupdf_cpp::MainPage::OpenDocument(StorageFile^ file) Point ras_size = ComputePageSize(spatial_info, k); auto render_task = - create_task(mu_doc->RenderPage(k, ras_size.X, ras_size.Y)); + create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y)); render_task.then([this, k, ras_size] (InMemoryRandomAccessStream^ ras) { @@ -641,7 +640,7 @@ void mupdf_cpp::MainPage::RenderRange(int curr_page) { Point ras_size = ComputePageSize(spatial_info, k); auto render_task = - create_task(mu_doc->RenderPage(k, ras_size.X, ras_size.Y)); + create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y)); render_task.then([this, k, ras_size] (InMemoryRandomAccessStream^ ras) { @@ -699,7 +698,7 @@ void mupdf_cpp::MainPage::Slider_ValueChanged(Platform::Object^ sender, Windows: spatial_info_t spatial_info = InitSpatial(1); Point ras_size = ComputePageSize(spatial_info, newValue); auto render_task = - create_task(mu_doc->RenderPage(newValue, ras_size.X, ras_size.Y)); + create_task(mu_doc->RenderPageAsync(newValue, ras_size.X, ras_size.Y)); render_task.then([this, newValue, ras_size] (InMemoryRandomAccessStream^ ras) { @@ -793,10 +792,10 @@ void mupdf_cpp::MainPage::ClearTextSearch() m_text_list->Clear(); } -void mupdf_cpp::MainPage::ShowSearchResults(SearchResult_t result) +void mupdf_cpp::MainPage::ShowSearchResults(int page_num, int box_count) { int old_page = this->m_currpage; - int new_page = result.page_num; + int new_page = page_num; ClearTextSearch(); @@ -814,7 +813,7 @@ void mupdf_cpp::MainPage::ShowSearchResults(SearchResult_t result) auto doc_page = this->m_docPages->GetAt(old_page); /* Construct our list of rectangles */ - for (int k = 0; k < result.box_count; k++) + for (int k = 0; k < box_count; k++) { RectList^ rect_item = ref new RectList(); auto curr_box = mu_doc->GetTextSearch(k); @@ -869,7 +868,9 @@ void mupdf_cpp::MainPage::SearchPrev(Platform::Object^ sender, Windows::UI::Xaml void mupdf_cpp::MainPage::CancelSearch(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { - m_searchcts.cancel(); + m_searchcts.cancel(); + xaml_ProgressStack->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + this->m_search_active = false; } void mupdf_cpp::MainPage::AddTextCanvas() @@ -884,6 +885,11 @@ void mupdf_cpp::MainPage::AddTextCanvas() this->m_search_active = false; } +void mupdf_cpp::MainPage::SearchProgress(IAsyncOperationWithProgress^ operation, double status) +{ + xaml_Progress->Value = status; +} + void mupdf_cpp::MainPage::SearchInDirection(int dir, String^ textToFind) { cancellation_token_source cts; @@ -891,55 +897,43 @@ void mupdf_cpp::MainPage::SearchInDirection(int dir, String^ textToFind) m_searchcts = cts; int pos = m_currpage; int start; - SearchResult_t result; - - result.box_count = 0; - result.page_num = -1; if (m_searchpage == pos) start = pos + dir; else start = pos; - /* ProgressBar^ my_xaml_Progress = (ProgressBar^) (this->FindName("xaml_Progress")); - my_xaml_Progress->Value = start; - my_xaml_Progress->IsEnabled = true; - my_xaml_Progress->Opacity = 1.0; */ - if (start < 0) return; if (start > this->m_num_pages - 1) return; this->m_search_active = true; - /* Do task lambdas here to avoid UI blocking issues */ - auto search_task = create_task([this, textToFind, dir, start, &result]()->SearchResult_t - { - for (int i = start; i >= 0 && i < this->m_num_pages; i += dir) - { - result.box_count = this->mu_doc->ComputeTextSearch(textToFind, i); - result.page_num = i; + ProgressBar^ my_xaml_Progress = (ProgressBar^) (this->FindName("xaml_Progress")); + xaml_ProgressStack->Visibility = Windows::UI::Xaml::Visibility::Visible; + auto temp = mu_doc->SearchDocumentWithProgressAsync(textToFind, dir, start); + temp->Progress = ref new AsyncOperationProgressHandler(this, &MainPage::SearchProgress); - // my_xaml_Progress->Value = i; + auto search_task = create_task(temp, token); - if (result.box_count > 0) - { - return result; - } - if (is_task_cancellation_requested()) - { - } - } - /* Todo no matches found alert */ - return result; - }, token); /* Do the continuation on the ui thread */ - search_task.then([this](task the_task) + auto con_task = search_task.then([this, textToFind](int page_num) { - SearchResult_t the_result = the_task.get(); - if (the_result.box_count > 0) + xaml_ProgressStack->Visibility = Windows::UI::Xaml::Visibility::Collapsed; + if (page_num == TEXT_NOT_FOUND) { - this->ShowSearchResults(the_result); + auto str1 = "\"" + textToFind + "\" Was Not Found In The Search"; + NotifyUser(str1, StatusMessage); + this->m_search_active = false; + } + else + { + int box_count = mu_doc->TextSearchCount(); + + if (box_count > 0) + { + this->ShowSearchResults(page_num, box_count); + } } }, task_continuation_context::use_current()); } @@ -1140,16 +1134,16 @@ void mupdf_cpp::MainPage::LinkTapped(Platform::Object^ sender, Windows::UI::Xaml // Launch the URI with a warning prompt concurrency::task launchUriOperation(Windows::System::Launcher::LaunchUriAsync(link->Urilink, launchOptions)); launchUriOperation.then([](bool success) - { - if (success) - { - // URI launched - } - else - { - // URI launch failed - } - }); + { + if (success) + { + // URI launched + } + else + { + // URI launch failed + } + }); } } } @@ -1257,6 +1251,7 @@ void mupdf_cpp::MainPage::UpdateAppBarButtonViewState() VisualStateManager::GoToState(Help, viewState, true); } +/* Manipulation zooming with touch input */ void mupdf_cpp::MainPage::ScrollChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs^ e) { @@ -1275,7 +1270,7 @@ void mupdf_cpp::MainPage::ScrollChanged(Platform::Object^ sender, Point ras_size = ComputePageSize(spatial_info, page); auto render_task = - create_task(mu_doc->RenderPage(page, ras_size.X, ras_size.Y)); + create_task(mu_doc->RenderPageAsync(page, ras_size.X, ras_size.Y)); render_task.then([this, page, ras_size] (InMemoryRandomAccessStream^ ras) { @@ -1283,3 +1278,39 @@ void mupdf_cpp::MainPage::ScrollChanged(Platform::Object^ sender, }, task_continuation_context::use_current()); } } + +/* Zoom in and out for keyboard only case */ +void MainPage::OnKeyDown(KeyRoutedEventArgs^ e) +{ + return; /* Waiting until I can get zoom factor in scroll viewer. */ + + auto doc_page = this->m_docPages->GetAt(m_currpage); + double curr_zoom = doc_page->Zoom; + + long val = (long) (e->Key); + if (val == KEY_PLUS) + { + curr_zoom = curr_zoom + 0.25; + if (curr_zoom > 4) curr_zoom = 4; + } + else if (val == KEY_MINUS) + { + curr_zoom = curr_zoom - 0.25; + if (curr_zoom < 0.25) curr_zoom = 0.25; + } else + return; + + doc_page->Zoom = curr_zoom; + int page = m_currpage; + /* Render at new resolution */ + spatial_info_t spatial_info = InitSpatial(doc_page->Zoom); + Point ras_size = ComputePageSize(spatial_info, page); + + auto render_task = + create_task(mu_doc->RenderPageAsync(page, ras_size.X, ras_size.Y)); + + render_task.then([this, page, ras_size] (InMemoryRandomAccessStream^ ras) + { + ReplaceImage(page, ras, ras_size); + }, task_continuation_context::use_current()); +} diff --git a/winrt/mupdf_cpp/MainPage.xaml.h b/winrt/mupdf_cpp/MainPage.xaml.h index 869297f4..f6cdb218 100644 --- a/winrt/mupdf_cpp/MainPage.xaml.h +++ b/winrt/mupdf_cpp/MainPage.xaml.h @@ -44,12 +44,6 @@ typedef enum { REN_PAGE /* Used to ignore value when source based setting */ } RenderingStatus_t; -typedef struct SearchResult_s -{ - int box_count; - int page_num; -} SearchResult_t; - typedef struct spatial_info_s { Point size; @@ -68,6 +62,7 @@ namespace mupdf_cpp protected: virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; + virtual void OnKeyDown(Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e) override; /* added */ private: @@ -102,6 +97,7 @@ namespace mupdf_cpp bool m_search_active; /* Used to avoid multiple UI clicks */ bool m_sliderchange; bool m_update_flip; + double m_Progress; void ReplaceImage(int page_num, InMemoryRandomAccessStream^ ras, Point ras_size); void Picker(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); @@ -122,7 +118,7 @@ namespace mupdf_cpp void SearchPrev(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void CancelSearch(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void SearchInDirection(int dir, String^ textToFind); - void ShowSearchResults(SearchResult_t result); + void ShowSearchResults(int page_num, int box_count); void ClearTextSearch(); void AddTextCanvas(); void GridSizeChanged(); @@ -151,5 +147,6 @@ namespace mupdf_cpp Point ComputePageSize(spatial_info_t spatial_info, int page_num); void ScrollChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs^ e); void LinkTapped(Platform::Object^ sender, Windows::UI::Xaml::Input::TappedRoutedEventArgs^ e); + void SearchProgress(IAsyncOperationWithProgress^ operation, double status); }; } diff --git a/winrt/mupdfwinrt/muctx.cpp b/winrt/mupdfwinrt/muctx.cpp index f069fbeb..8651ffa5 100644 --- a/winrt/mupdfwinrt/muctx.cpp +++ b/winrt/mupdfwinrt/muctx.cpp @@ -502,6 +502,18 @@ HRESULT muctx::RenderPage(int page_num, int width, int height, return S_OK; } +bool muctx::RequiresPassword(void) +{ + return fz_needs_password(mu_doc); +} + +bool muctx::ApplyPassword(String^ password) +{ + /* Need to do String to char here */ + // return fz_authenticate_password(mu_doc, password) != 0; + return 0; +} + String^ muctx::GetHTML(int page_num) { fz_output *out = NULL; diff --git a/winrt/mupdfwinrt/muctx.h b/winrt/mupdfwinrt/muctx.h index 15ebf5ef..c43c7404 100644 --- a/winrt/mupdfwinrt/muctx.h +++ b/winrt/mupdfwinrt/muctx.h @@ -95,4 +95,6 @@ public: int GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec); int GetContents(sh_vector_content contents_vec); String^ GetHTML(int page_num); + bool RequiresPassword(void); + bool ApplyPassword(String^ password); }; diff --git a/winrt/mupdfwinrt/mudocument.cpp b/winrt/mupdfwinrt/mudocument.cpp index c3003e96..ec661b27 100644 --- a/winrt/mupdfwinrt/mudocument.cpp +++ b/winrt/mupdfwinrt/mudocument.cpp @@ -17,6 +17,16 @@ mudocument::mudocument() this->links = nullptr; } +bool mudocument::RequiresPassword() +{ + return mu_object.RequiresPassword(); +} + +bool mudocument::ApplyPassword(String^ password) +{ + return mu_object.ApplyPassword(password); +} + void mudocument::CleanUp() { this->mu_object.CleanUp(); @@ -33,7 +43,7 @@ Point mudocument::GetPageSize(int page_num) return this->mu_object.MeasurePage(page_num); } -Windows::Foundation::IAsyncAction^ mudocument::OpenFile(StorageFile^ file) +Windows::Foundation::IAsyncAction^ mudocument::OpenFileAsync(StorageFile^ file) { return create_async([this, file]() { @@ -98,9 +108,58 @@ static void Prepare_bmp(int width, int height, DataWriter ^dw) dw->WriteInt32(0); } -/* Pack the page into a bmp stream so that we can use it with an image brush */ +/* Do the search through the pages with an async task with progress callback */ +Windows::Foundation::IAsyncOperationWithProgress^ + mudocument::SearchDocumentWithProgressAsync(String^ textToFind, int dir, int start_page) +{ + return create_async([this, textToFind, dir, start_page](progress_reporter 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^ - mudocument::RenderPage(int page_num, int width, int height) + mudocument::RenderPageAsync(int page_num, int width, int height) { return create_async([this, width, height, page_num](cancellation_token ct) -> InMemoryRandomAccessStream^ { @@ -195,6 +254,15 @@ int mudocument::ComputeTextSearch(String^ text, int page_num) 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) { diff --git a/winrt/mupdfwinrt/mudocument.h b/winrt/mupdfwinrt/mudocument.h index a271d74c..d9bd7c1f 100644 --- a/winrt/mupdfwinrt/mudocument.h +++ b/winrt/mupdfwinrt/mudocument.h @@ -2,7 +2,7 @@ /* 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 */ + C#, C++, and JavaScript applications */ #include "muctx.h" #include "Links.h" @@ -16,6 +16,10 @@ using namespace Platform; using namespace Concurrency; using namespace Platform::Collections; +#define SEARCH_FORWARD 1 +#define SEARCH_BACKWARD -1 +#define TEXT_NOT_FOUND -1 + namespace mupdfwinrt { public ref class mudocument sealed @@ -29,17 +33,22 @@ namespace mupdfwinrt public: mudocument(); void CleanUp(); - Windows::Foundation::IAsyncAction^ OpenFile(StorageFile^ file); + Windows::Foundation::IAsyncAction^ OpenFileAsync(StorageFile^ file); int GetNumPages(void); Point GetPageSize(int page_num); Windows::Foundation::IAsyncOperation^ - RenderPage(int page_num, int width, int height); + RenderPageAsync(int page_num, int width, int height); + Windows::Foundation::IAsyncOperationWithProgress^ + SearchDocumentWithProgressAsync(String^ textToFind, int dir, int start_page); String^ ComputeHTML(int page_num); int ComputeTextSearch(String^ text, int page_num); Links^ GetTextSearch(int k); + int TextSearchCount(void); int ComputeContents(void); ContentItem^ GetContent(int k); int ComputeLinks(int page_num); Links^ GetLink(int k); + bool RequiresPassword(); + bool ApplyPassword(String^ password); }; } -- cgit v1.2.3