summaryrefslogtreecommitdiff
path: root/platform/winrt
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2013-10-23 21:31:51 -0700
committerMichael Vrhel <michael.vrhel@artifex.com>2013-10-23 21:33:33 -0700
commit52dd8a3e321bb965f8f02494026d545fddf54c01 (patch)
treeee9433ab5977e2ecec88f10197d16fd5b5d758e2 /platform/winrt
parent3379beab77726c2be11e369113f4ca795ff883d9 (diff)
downloadmupdf-52dd8a3e321bb965f8f02494026d545fddf54c01.tar.xz
Fix so that multi-threaded rendering of display list works.
Proper use of mutex lock in areas where we multiple threads can not be accessing the document or page level objects at the same time. With this fix, multiple threads can be rendering different display lists at the same time. Also fix for use of page selection scroll bar so that it does not render the page until the user lifts off the bar. This is the same as the Android app and avoids smaller devices getting overloaded if you do rapid scrolling in a document.
Diffstat (limited to 'platform/winrt')
-rw-r--r--platform/winrt/mupdf_cpp/MainPage.xaml2
-rw-r--r--platform/winrt/mupdf_cpp/MainPage.xaml.cpp75
-rw-r--r--platform/winrt/mupdf_cpp/MainPage.xaml.h5
-rw-r--r--platform/winrt/mupdfwinrt/Cache.cpp10
-rw-r--r--platform/winrt/mupdfwinrt/Cache.h8
-rw-r--r--platform/winrt/mupdfwinrt/muctx.cpp202
-rw-r--r--platform/winrt/mupdfwinrt/muctx.h10
-rw-r--r--platform/winrt/mupdfwinrt/mudocument.cpp82
-rw-r--r--platform/winrt/mupdfwinrt/mudocument.h3
9 files changed, 224 insertions, 173 deletions
diff --git a/platform/winrt/mupdf_cpp/MainPage.xaml b/platform/winrt/mupdf_cpp/MainPage.xaml
index 22fbe5da..eaf096e3 100644
--- a/platform/winrt/mupdf_cpp/MainPage.xaml
+++ b/platform/winrt/mupdf_cpp/MainPage.xaml
@@ -14,7 +14,7 @@
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
- <Slider x:Name="xaml_PageSlider" Minimum="0" Maximum="10" ValueChanged="Slider_ValueChanged" Grid.Column="0" Margin="10,0" VerticalAlignment="Center" />
+ <Slider x:Name="xaml_PageSlider" Minimum="0" Maximum="10" PointerCaptureLost="Slider_ValueChanged" Grid.Column="0" Margin="10,0" VerticalAlignment="Center" />
<Button x:Name="Find_File" Style="{StaticResource OpenFileAppBarButtonStyle}" Tag="OpenFile" HorizontalAlignment="Right" Grid.Column="1" Click="Picker"/>
</Grid>
</AppBar>
diff --git a/platform/winrt/mupdf_cpp/MainPage.xaml.cpp b/platform/winrt/mupdf_cpp/MainPage.xaml.cpp
index d31c2b94..166d81cf 100644
--- a/platform/winrt/mupdf_cpp/MainPage.xaml.cpp
+++ b/platform/winrt/mupdf_cpp/MainPage.xaml.cpp
@@ -6,7 +6,7 @@
#include "pch.h"
#include "MainPage.xaml.h"
-#define LOOK_AHEAD 0 /* A +/- count on the pages to pre-render */
+#define LOOK_AHEAD 1 /* A +/- count on the pages to pre-render */
#define THUMB_PREADD 10
#define MIN_SCALE 0.5
@@ -737,18 +737,44 @@ void mupdf_cpp::MainPage::RenderRange(int curr_page)
}
}
-void mupdf_cpp::MainPage::Slider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e)
+void mupdf_cpp::MainPage::FlipView_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)
+{
+ if (m_init_done && !m_page_update)
+ {
+ int pos = this->m_curr_flipView->SelectedIndex;
+
+ if (pos >= 0)
+ {
+ if (xaml_PageSlider->IsEnabled)
+ {
+ xaml_PageSlider->Value = pos;
+ }
+ if (m_sliderchange)
+ {
+ m_sliderchange = false;
+ return;
+ }
+ else
+ {
+ /* Make sure to clear any text search */
+ auto doc_old = this->m_docPages->GetAt(m_currpage);
+ doc_old->TextBox = nullptr;
+ }
+ /* Get the current page */
+ int curr_page = this->m_currpage;
+ this->RenderRange(pos);
+ this->ReleasePages(curr_page, pos);
+ }
+ }
+}
+
+void mupdf_cpp::MainPage::Slider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
{
int newValue = (int) this->xaml_PageSlider->Value - 1; /* zero based */
if (IsNotStandardView())
return;
- if (m_update_flip)
- {
- m_update_flip = false;
- return;
- }
if (m_init_done && this->xaml_PageSlider->IsEnabled)
{
/* Make sure to clear any text search */
@@ -778,38 +804,6 @@ void mupdf_cpp::MainPage::Slider_ValueChanged(Platform::Object^ sender, Windows:
}
}
-void mupdf_cpp::MainPage::FlipView_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)
-{
- if (m_init_done && !m_page_update)
- {
- int pos = this->m_curr_flipView->SelectedIndex;
-
- if (pos >= 0)
- {
- m_update_flip = true;
- if (xaml_PageSlider->IsEnabled)
- {
- xaml_PageSlider->Value = pos;
- }
- if (m_sliderchange)
- {
- m_sliderchange = false;
- return;
- }
- else
- {
- /* Make sure to clear any text search */
- auto doc_old = this->m_docPages->GetAt(m_currpage);
- doc_old->TextBox = nullptr;
- }
- /* Get the current page */
- int curr_page = this->m_currpage;
- this->RenderRange(pos);
- this->ReleasePages(curr_page, pos);
- }
- }
-}
-
/* Search Related Code */
void mupdf_cpp::MainPage::Searcher(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
@@ -975,7 +969,8 @@ void mupdf_cpp::MainPage::SearchInDirection(int dir, String^ textToFind)
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);
+ auto temp = mu_doc->SearchDocumentWithProgressAsync(textToFind, dir, start,
+ m_num_pages);
temp->Progress = ref new AsyncOperationProgressHandler<int, double>(this, &MainPage::SearchProgress);
auto search_task = create_task(temp, token);
diff --git a/platform/winrt/mupdf_cpp/MainPage.xaml.h b/platform/winrt/mupdf_cpp/MainPage.xaml.h
index 80978bc8..417073e4 100644
--- a/platform/winrt/mupdf_cpp/MainPage.xaml.h
+++ b/platform/winrt/mupdf_cpp/MainPage.xaml.h
@@ -109,7 +109,6 @@ namespace mupdf_cpp
bool m_insearch; /* Used for UI display */
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);
@@ -125,7 +124,6 @@ namespace mupdf_cpp
void HandleFileNotFoundException(Platform::COMException^ e);
void NotifyUserFileNotExist();
void SetFlipView();
- void Slider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e);
void Slider_Released(Platform::Object^ sender, Windows::UI::Xaml::Controls::Primitives::RangeBaseValueChangedEventArgs^ e);
void FlipView_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e);
void SearchNext(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
@@ -173,5 +171,6 @@ namespace mupdf_cpp
void Page_Loaded(Object^ sender, RoutedEventArgs^ e);
Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs^ _protocolEventArgs;
Windows::ApplicationModel::Activation::FileActivatedEventArgs^ _fileEventArgs;
- };
+ void Slider_ValueChanged(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
+};
}
diff --git a/platform/winrt/mupdfwinrt/Cache.cpp b/platform/winrt/mupdfwinrt/Cache.cpp
index 77e253f0..b129710f 100644
--- a/platform/winrt/mupdfwinrt/Cache.cpp
+++ b/platform/winrt/mupdfwinrt/Cache.cpp
@@ -22,6 +22,7 @@ void Cache::Empty(fz_context *mu_ctx)
cache_entry_t *old_entry = curr_entry;
curr_entry = old_entry->next;
fz_drop_display_list(mu_ctx, old_entry->dlist);
+
delete old_entry;
}
this->size = 0;
@@ -30,7 +31,8 @@ void Cache::Empty(fz_context *mu_ctx)
}
}
-void Cache::AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx)
+void Cache::Add(int value, int width_in, int height_in, fz_display_list *dlist,
+ fz_context *mu_ctx)
{
std::lock_guard<std::mutex> lock(cache_lock);
@@ -58,6 +60,8 @@ void Cache::AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx)
new_entry->dlist = dlist;
new_entry->index = value;
+ new_entry->width = width_in;
+ new_entry->height = height_in;
new_entry->prev = NULL;
if (head == NULL)
{
@@ -76,7 +80,7 @@ void Cache::AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx)
fz_keep_display_list(mu_ctx, new_entry->dlist);
}
-fz_display_list* Cache::UseEntry(int value, fz_context *mu_ctx)
+fz_display_list* Cache::Use(int value, int *width_out, int *height_out, fz_context *mu_ctx)
{
std::lock_guard<std::mutex> lock(cache_lock);
cache_entry_t *curr_entry = this->head;
@@ -107,6 +111,8 @@ fz_display_list* Cache::UseEntry(int value, fz_context *mu_ctx)
head->prev = curr_entry;
head = curr_entry;
}
+ *width_out = curr_entry->width;
+ *height_out = curr_entry->height;
return curr_entry->dlist;
}
else
diff --git a/platform/winrt/mupdfwinrt/Cache.h b/platform/winrt/mupdfwinrt/Cache.h
index 0763dba4..e8c9801d 100644
--- a/platform/winrt/mupdfwinrt/Cache.h
+++ b/platform/winrt/mupdfwinrt/Cache.h
@@ -11,6 +11,9 @@ typedef struct cache_entry_s cache_entry_t;
struct cache_entry_s
{
+ int number;
+ int width;
+ int height;
fz_display_list *dlist;
cache_entry_t *next;
cache_entry_t *prev;
@@ -28,7 +31,8 @@ private:
public:
Cache(void);
~Cache(void);
- fz_display_list* UseEntry(int value, fz_context *mu_ctx);
- void AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx);
+ void GetSize(int *width, int *height);
+ fz_display_list* Use(int value, int *width, int *height, fz_context *mu_ctx);
+ void Add(int value, int width, int height, fz_display_list *dlist, fz_context *mu_ctx);
void Empty(fz_context *mu_ctx);
};
diff --git a/platform/winrt/mupdfwinrt/muctx.cpp b/platform/winrt/mupdfwinrt/muctx.cpp
index 56c6f3a9..98aa7fc6 100644
--- a/platform/winrt/mupdfwinrt/muctx.cpp
+++ b/platform/winrt/mupdfwinrt/muctx.cpp
@@ -93,11 +93,11 @@ void muctx::CleanUp(void)
{
fz_free_outline(mu_ctx, mu_outline);
fz_close_document(mu_doc);
- display_list_cache->Empty(mu_ctx);
+ page_cache->Empty(mu_ctx);
fz_free_context(mu_ctx);
- delete display_list_cache;
- display_list_cache = NULL;
+ delete page_cache;
+ page_cache = NULL;
this->mu_ctx = NULL;
this->mu_doc = NULL;
this->mu_outline = NULL;
@@ -133,7 +133,7 @@ muctx::muctx(void)
mu_ctx = NULL;
mu_doc = NULL;
mu_outline = NULL;
- display_list_cache = new Cache();
+ page_cache = new Cache();
}
/* Destructor */
@@ -141,14 +141,14 @@ muctx::~muctx(void)
{
fz_free_outline(mu_ctx, mu_outline);
fz_close_document(mu_doc);
- display_list_cache->Empty(mu_ctx);
+ page_cache->Empty(mu_ctx);
fz_free_context(mu_ctx);
mu_ctx = NULL;
mu_doc = NULL;
mu_outline = NULL;
- delete display_list_cache;
- display_list_cache = NULL;
+ delete page_cache;
+ page_cache = NULL;
}
/* Set up the stream access */
@@ -250,13 +250,10 @@ void muctx::FlattenOutline(fz_outline *outline, int level,
int muctx::GetContents(sh_vector_content contents_vec)
{
fz_outline *root = NULL;
- fz_context *ctx_clone = NULL;
int has_content = 0;
- ctx_clone = fz_clone_context(mu_ctx);
-
fz_var(root);
- fz_try(ctx_clone)
+ fz_try(mu_ctx)
{
root = fz_load_outline(mu_doc);
if (root != NULL)
@@ -265,16 +262,14 @@ int muctx::GetContents(sh_vector_content contents_vec)
FlattenOutline(root, 0, contents_vec);
}
}
- fz_always(ctx_clone)
+ fz_always(mu_ctx)
{
- fz_free_outline(ctx_clone, root);
+ fz_free_outline(mu_ctx, root);
}
- fz_catch(ctx_clone)
+ fz_catch(mu_ctx)
{
- fz_free_context(ctx_clone);
return E_FAIL;
}
- fz_free_context(ctx_clone);
return has_content;
}
@@ -283,26 +278,23 @@ int muctx::GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec)
fz_page *page = NULL;
fz_text_sheet *sheet = NULL;
fz_device *dev = NULL;
- fz_context *ctx_clone = NULL;
fz_text_page *text = NULL;
int hit_count = 0;
int k;
- ctx_clone = fz_clone_context(mu_ctx);
-
fz_var(page);
fz_var(sheet);
fz_var(dev);
- fz_try(ctx_clone)
+ fz_try(mu_ctx)
{
page = fz_load_page(mu_doc, page_num);
- sheet = fz_new_text_sheet(ctx_clone);
- text = fz_new_text_page(ctx_clone);
- dev = fz_new_text_device(ctx_clone, sheet, text);
+ sheet = fz_new_text_sheet(mu_ctx);
+ text = fz_new_text_page(mu_ctx);
+ dev = fz_new_text_device(mu_ctx, 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));
+ hit_count = fz_search_text_page(mu_ctx, text, needle, mu_hit_bbox, nelem(mu_hit_bbox));
for (k = 0; k < hit_count; k++)
{
@@ -314,19 +306,17 @@ int muctx::GetTextSearch(int page_num, char* needle, sh_vector_text texts_vec)
texts_vec->push_back(text_search);
}
}
- fz_always(ctx_clone)
+ fz_always(mu_ctx)
{
fz_free_page(mu_doc, page);
fz_free_device(dev);
- fz_free_text_sheet(ctx_clone, sheet);
- fz_free_text_page(ctx_clone, text);
+ fz_free_text_sheet(mu_ctx, sheet);
+ fz_free_text_page(mu_ctx, text);
}
- fz_catch(ctx_clone)
+ fz_catch(mu_ctx)
{
- fz_free_context(ctx_clone);
return E_FAIL;
}
- fz_free_context(ctx_clone);
return hit_count;
}
@@ -335,15 +325,12 @@ int muctx::GetLinks(int page_num, sh_vector_link links_vec)
{
fz_page *page = NULL;
fz_link *links = NULL;
- fz_context *ctx_clone = NULL;
int k = 0;
int num_links = 0;
- ctx_clone = fz_clone_context(mu_ctx);
-
fz_var(page);
fz_var(links);
- fz_try(ctx_clone)
+ fz_try(mu_ctx)
{
page = fz_load_page(mu_doc, page_num);
links = fz_load_links(mu_doc, page);
@@ -390,30 +377,26 @@ int muctx::GetLinks(int page_num, sh_vector_link links_vec)
}
}
}
- fz_always(ctx_clone)
+ fz_always(mu_ctx)
{
fz_free_page(mu_doc, page);
- fz_drop_link(ctx_clone, links);
+ fz_drop_link(mu_ctx, links);
}
- fz_catch(ctx_clone)
+ fz_catch(mu_ctx)
{
- fz_free_context(ctx_clone);
return E_FAIL;
}
- fz_free_context(ctx_clone);
return num_links;
}
-fz_display_list * muctx::CreateDisplayList(int page_num)
+fz_display_list * muctx::CreateDisplayList(int page_num, int *width, int *height)
{
- fz_context *ctx_clone = NULL;
fz_device *dev = NULL;
fz_page *page = NULL;
-
- ctx_clone = fz_clone_context(mu_ctx);
+ Point page_size;
/* First see if we have this one in the cache */
- fz_display_list *dlist = display_list_cache->UseEntry(page_num, ctx_clone);
+ fz_display_list *dlist = page_cache->Use(page_num, width, height, mu_ctx);
if (dlist != NULL)
return dlist;
@@ -422,80 +405,67 @@ fz_display_list * muctx::CreateDisplayList(int page_num)
fz_var(page);
fz_var(dlist);
- fz_try(ctx_clone)
+ fz_try(mu_ctx)
{
page = fz_load_page(mu_doc, page_num);
/* Create a new list */
- dlist = fz_new_display_list(ctx_clone);
- dev = fz_new_list_device(ctx_clone, dlist);
+ dlist = fz_new_display_list(mu_ctx);
+ dev = fz_new_list_device(mu_ctx, dlist);
fz_run_page_contents(mu_doc, page, dev, &fz_identity, NULL);
+ page_size = MeasurePage(page);
+ *width = page_size.X;
+ *height = page_size.Y;
/* Add it to the cache and set that it is in use */
- display_list_cache->AddEntry(page_num, dlist, ctx_clone);
+ page_cache->Add(page_num, *width, *height, dlist, mu_ctx);
}
- fz_always(ctx_clone)
+ fz_always(mu_ctx)
{
fz_free_device(dev);
fz_free_page(mu_doc, page);
}
- fz_catch(ctx_clone)
+ fz_catch(mu_ctx)
{
- fz_drop_display_list(ctx_clone, dlist);
- fz_free_context(ctx_clone);
+ fz_drop_display_list(mu_ctx, dlist);
return NULL;
}
return dlist;
}
-/* Render page_num to size width by height into bmp_data buffer */
-status_t muctx::RenderPage(int page_num, int width, int height,
- unsigned char *bmp_data, bool use_dlist)
+/* Render display list bmp_data buffer. No lock needed for this operation */
+status_t muctx::RenderPageMT(void *dlist, int page_width, int page_height,
+ unsigned char *bmp_data, int bmp_width, int bmp_height)
{
fz_device *dev = NULL;
fz_pixmap *pix = NULL;
- fz_page *page = NULL;
fz_matrix ctm, *pctm = &ctm;
- Point page_size;
fz_context *ctx_clone = NULL;
- fz_display_list *dlist = NULL;
-
- if (use_dlist)
- if ((dlist = CreateDisplayList(page_num)) == NULL)
- return E_FAILURE;
+ fz_display_list *display_list = (fz_display_list*) dlist;
ctx_clone = fz_clone_context(mu_ctx);
fz_var(dev);
fz_var(pix);
- fz_var(page);
- fz_var(dlist);
+ fz_var(display_list);
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);
+ pctm = fz_scale(pctm, (float) bmp_width / page_width, (float) bmp_height / page_height);
/* Flip on Y */
- ctm.f = height;
+ ctm.f = bmp_height;
ctm.d = -ctm.d;
- pix = fz_new_pixmap_with_data(ctx_clone, fz_device_bgr(ctx_clone), width, height, bmp_data);
+ pix = fz_new_pixmap_with_data(ctx_clone, fz_device_bgr(ctx_clone), bmp_width,
+ bmp_height, bmp_data);
fz_clear_pixmap_with_value(ctx_clone, pix, 255);
dev = fz_new_draw_device(ctx_clone, pix);
- if (use_dlist)
- fz_run_display_list(dlist, dev, pctm, NULL, NULL);
- else
- fz_run_page(mu_doc, page, dev, pctm, NULL);
+ fz_run_display_list(display_list, dev, pctm, NULL, NULL);
}
fz_always(ctx_clone)
{
fz_free_device(dev);
fz_drop_pixmap(ctx_clone, pix);
- fz_free_page(mu_doc, page);
- if (use_dlist)
- fz_drop_display_list(ctx_clone, dlist);
-
+ fz_drop_display_list(ctx_clone, display_list);
}
fz_catch(ctx_clone)
{
@@ -507,6 +477,50 @@ status_t muctx::RenderPage(int page_num, int width, int height,
return S_ISOK;
}
+/* Render page_num to size width by height into bmp_data buffer. Lock needed. */
+status_t muctx::RenderPage(int page_num, unsigned char *bmp_data, int bmp_width,
+ int bmp_height)
+{
+ fz_device *dev = NULL;
+ fz_pixmap *pix = NULL;
+ fz_page *page = NULL;
+ fz_matrix ctm, *pctm = &ctm;
+ Point page_size;
+
+ fz_var(dev);
+ fz_var(pix);
+ fz_var(page);
+
+ fz_try(mu_ctx)
+ {
+ 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) bmp_width / page_size.X,
+ (float) bmp_height / page_size.Y);
+ /* Flip on Y */
+ ctm.f = bmp_height;
+ ctm.d = -ctm.d;
+ pix = fz_new_pixmap_with_data(mu_ctx, fz_device_bgr(mu_ctx), bmp_width,
+ bmp_height, bmp_data);
+ fz_clear_pixmap_with_value(mu_ctx, pix, 255);
+ dev = fz_new_draw_device(mu_ctx, pix);
+ fz_run_page(mu_doc, page, dev, pctm, NULL);
+ }
+ fz_always(mu_ctx)
+ {
+ fz_free_device(dev);
+ fz_drop_pixmap(mu_ctx, pix);
+ fz_free_page(mu_doc, page);
+ }
+ fz_catch(mu_ctx)
+ {
+ return E_FAILURE;
+ }
+ return S_ISOK;
+}
+
bool muctx::RequiresPassword(void)
{
return fz_needs_password(mu_doc);
@@ -524,46 +538,40 @@ String^ muctx::GetHTML(int page_num)
fz_page *page = NULL;
fz_text_sheet *sheet = NULL;
fz_text_page *text = NULL;
- fz_context *ctx_clone = NULL;
fz_buffer *buf = NULL;
String^ html;
- ctx_clone = fz_clone_context(mu_ctx);
-
fz_var(dev);
fz_var(page);
fz_var(sheet);
fz_var(text);
fz_var(buf);
- fz_try(ctx_clone)
+ fz_try(mu_ctx)
{
page = fz_load_page(mu_doc, page_num);
- sheet = fz_new_text_sheet(ctx_clone);
- text = fz_new_text_page(ctx_clone);
- dev = fz_new_text_device(ctx_clone, sheet, text);
+ sheet = fz_new_text_sheet(mu_ctx);
+ text = fz_new_text_page(mu_ctx);
+ dev = fz_new_text_device(mu_ctx, sheet, text);
fz_run_page(mu_doc, page, dev, &fz_identity, NULL);
fz_free_device(dev);
dev = NULL;
- fz_analyze_text(ctx_clone, sheet, text);
- buf = fz_new_buffer(ctx_clone, 256);
- out = fz_new_output_with_buffer(ctx_clone, buf);
- fz_print_text_page_html(ctx_clone, out, text);
+ fz_analyze_text(mu_ctx, sheet, text);
+ buf = fz_new_buffer(mu_ctx, 256);
+ out = fz_new_output_with_buffer(mu_ctx, buf);
+ fz_print_text_page_html(mu_ctx, out, text);
html = char_to_String((char*) buf->data);
}
- fz_always(ctx_clone)
+ fz_always(mu_ctx)
{
fz_free_device(dev);
fz_free_page(mu_doc, page);
- fz_free_text_sheet(ctx_clone, sheet);
- fz_free_text_page(ctx_clone, text);
- fz_drop_buffer(ctx_clone, buf);
+ fz_free_text_sheet(mu_ctx, sheet);
+ fz_free_text_page(mu_ctx, text);
+ fz_drop_buffer(mu_ctx, buf);
}
- fz_catch(ctx_clone)
+ fz_catch(mu_ctx)
{
- fz_free_context(ctx_clone);
return nullptr;
}
-
- fz_free_context(ctx_clone);
return html;
}
diff --git a/platform/winrt/mupdfwinrt/muctx.h b/platform/winrt/mupdfwinrt/muctx.h
index 826fa45b..cce78a29 100644
--- a/platform/winrt/mupdfwinrt/muctx.h
+++ b/platform/winrt/mupdfwinrt/muctx.h
@@ -76,8 +76,7 @@ private:
fz_rect mu_hit_bbox[MAX_SEARCH];
void FlattenOutline(fz_outline *outline, int level,
sh_vector_content contents_vec);
- Cache *display_list_cache;
- fz_display_list* CreateDisplayList(int page_num);
+ Cache *page_cache;
public:
muctx(void);
@@ -86,8 +85,11 @@ public:
status_t InitializeStream(IRandomAccessStream^ readStream, char *ext);
int GetPageCount();
status_t InitializeContext();
- status_t RenderPage(int page_num, int width, int height, unsigned char *bmp_data,
- bool use_dlist);
+ status_t RenderPage(int page_num, unsigned char *bmp_data, int bmp_width,
+ int bmp_height);
+ status_t RenderPageMT(void *dlist, int page_width, int page_height,
+ unsigned char *bmp_data, int bmp_width, int bmp_height);
+ fz_display_list* CreateDisplayList(int page_num, int *width, int *height);
Point MeasurePage(int page_num);
Point MeasurePage(fz_page *page);
int GetLinks(int page_num, sh_vector_link links_vec);
diff --git a/platform/winrt/mupdfwinrt/mudocument.cpp b/platform/winrt/mupdfwinrt/mudocument.cpp
index 92c24e24..7c90ba18 100644
--- a/platform/winrt/mupdfwinrt/mudocument.cpp
+++ b/platform/winrt/mupdfwinrt/mudocument.cpp
@@ -43,8 +43,12 @@ int mudocument::GetNumPages()
Point mudocument::GetPageSize(int page_num)
{
- std::lock_guard<std::mutex> lock(mutex_lock);
- return this->mu_object.MeasurePage(page_num);
+ Point size;
+
+ mutex_lock.lock();
+ size = this->mu_object.MeasurePage(page_num);
+ mutex_lock.unlock();
+ return size;
}
Windows::Foundation::IAsyncOperation<int>^ mudocument::OpenFileAsync(StorageFile^ file)
@@ -116,11 +120,12 @@ static void Prepare_bmp(int width, int height, DataWriter ^dw)
/* 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)
+ mudocument::SearchDocumentWithProgressAsync(String^ textToFind, int dir,
+ int start_page, int num_pages)
{
- return create_async([this, textToFind, dir, start_page](progress_reporter<double> reporter) -> int
+ return create_async([this, textToFind, dir, start_page, num_pages]
+ (progress_reporter<double> reporter) -> int
{
- int num_pages = this->GetNumPages();
double progress;
int box_count, result;
@@ -155,7 +160,6 @@ Windows::Foundation::IAsyncOperationWithProgress<int, double>^
}
}
reporter.report(100.0);
- /* Todo no matches found alert */
if (box_count == 0)
return TEXT_NOT_FOUND;
else
@@ -165,24 +169,47 @@ Windows::Foundation::IAsyncOperationWithProgress<int, double>^
/* Pack the page into a bmp stream */
Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
- mudocument::RenderPageAsync(int page_num, int width, int height, bool use_dlist)
+ mudocument::RenderPageAsync(int page_num, int bmp_width, int bmp_height,
+ bool use_dlist)
{
- return create_async([this, width, height, page_num, use_dlist](cancellation_token ct) -> InMemoryRandomAccessStream^
+ return create_async([this, bmp_width, bmp_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);
+ Array<unsigned char>^ bmp_data =
+ ref new Array<unsigned char>(bmp_height * 4 * bmp_width);
/* Set up the memory stream */
InMemoryRandomAccessStream ^ras = ref new InMemoryRandomAccessStream();
DataWriter ^dw = ref new DataWriter(ras->GetOutputStreamAt(0));
+ status_t code;
/* Go ahead and write our header data into the memory stream */
- Prepare_bmp(width, height, dw);
-
- std::lock_guard<std::mutex> lock(mutex_lock);
+ Prepare_bmp(bmp_width, bmp_height, dw);
- /* Get raster bitmap stream */
- status_t code = mu_object.RenderPage(page_num, width, height, &(bmp_data[0]),
- use_dlist);
+ if (use_dlist)
+ {
+ void *dlist;
+ int page_height;
+ int page_width;
+
+ mutex_lock.lock();
+ /* This lock will keep out issues in mupdf as well as race conditions
+ in the page cache */
+ dlist = (void*) mu_object.CreateDisplayList(page_num, &page_width,
+ &page_height);
+ /* Rendering of display list can occur with other threads so unlock */
+ mutex_lock.unlock();
+ code = mu_object.RenderPageMT(dlist, page_width, page_height,
+ &(bmp_data[0]), bmp_width, bmp_height);
+ }
+ else
+ {
+ /* Rendering in immediate mode. Keep lock in place */
+ mutex_lock.lock();
+ code = mu_object.RenderPage(page_num, &(bmp_data[0]), bmp_width,
+ bmp_height);
+ mutex_lock.unlock();
+ }
if (code != S_ISOK)
{
throw ref new FailureException("Page Rendering Failed");
@@ -200,11 +227,12 @@ Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
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>());
+ mutex_lock.lock();
int num_items = mu_object.GetLinks(page_num, link_smart_ptr_vec);
+ mutex_lock.unlock();
if (num_items == 0)
return 0;
/* Pack into winRT type*/
@@ -237,13 +265,16 @@ Links^ mudocument::GetLink(int 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;
+
+ mutex_lock.lock();
+ num_items = mu_object.GetTextSearch(page_num, text_char, text_smart_ptr_vec);
+ mutex_lock.unlock();
- int num_items = mu_object.GetTextSearch(page_num, text_char, text_smart_ptr_vec);
if (num_items == 0)
return 0;
/* Pack into winRT type*/
@@ -280,13 +311,14 @@ Links^ mudocument::GetTextSearch(int 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;
- int has_content = mu_object.GetContents(content_smart_ptr_vec);
+ mutex_lock.lock();
+ has_content = mu_object.GetContents(content_smart_ptr_vec);
+ mutex_lock.unlock();
if (!has_content)
return 0;
@@ -315,6 +347,10 @@ ContentItem^ mudocument::GetContent(int k)
String^ mudocument::ComputeHTML(int page_num)
{
- std::lock_guard<std::mutex> lock(mutex_lock);
- return mu_object.GetHTML(page_num);
+ String^ html;
+
+ mutex_lock.lock();
+ html = mu_object.GetHTML(page_num);
+ mutex_lock.unlock();
+ return html;
}
diff --git a/platform/winrt/mupdfwinrt/mudocument.h b/platform/winrt/mupdfwinrt/mudocument.h
index bb4de722..eebe1fbe 100644
--- a/platform/winrt/mupdfwinrt/mudocument.h
+++ b/platform/winrt/mupdfwinrt/mudocument.h
@@ -35,7 +35,8 @@ namespace mupdfwinrt
Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
RenderPageAsync(int page_num, int width, int height, bool use_dlist);
Windows::Foundation::IAsyncOperationWithProgress<int, double>^
- SearchDocumentWithProgressAsync(String^ textToFind, int dir, int start_page);
+ SearchDocumentWithProgressAsync(String^ textToFind, int dir,
+ int start_page, int num_pages);
String^ ComputeHTML(int page_num);
int ComputeTextSearch(String^ text, int page_num);
Links^ GetTextSearch(int k);