//
// MainPage.xaml.cpp
// Implementation of the MainPage class.
//
#include "pch.h"
#include "MainPage.xaml.h"
#include "LVContents.h"
#define LOOK_AHEAD 1 /* A +/- count on the pages to pre-render */
#define MIN_SCALE 0.5
#define MAX_SCALE 4
#define MARGIN_BUFF 400
#define MAX_SEARCH 500
#define SCALE_THUMB 0.25
static float screenScale = 1;
static fz_context *ctx = NULL;
fz_document *m_doc;
int linkPage[MAX_SEARCH];
char *linkUrl[MAX_SEARCH];
using namespace winapp;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace Windows::Graphics::Display;
using namespace ListViewContents;
//****************** Added *****************
using namespace Windows::Storage::Pickers;
using namespace Windows::Devices::Enumeration;
using namespace concurrency;
using namespace Windows::Graphics::Imaging;
//****************** End Add ****************
typedef struct win_stream_struct_s
{
IRandomAccessStream^ stream;
} win_stream_struct;
static win_stream_struct win_stream;
#ifndef NDEBUG
unsigned int _mainThreadId = 0U;
#ifdef __cplusplus
extern "C" {
#endif
// The IsMainThread function returns true if the current thread is the app's main thread and false otherwise.
bool IsMainThread()
{
return (_mainThreadId == GetCurrentThreadId());
}
// The IsBackgroundThread function returns false if the current thread is the app's main thread and true otherwise.
bool IsBackgroundThread()
{
return (_mainThreadId != GetCurrentThreadId());
}
// The RecordMainThread function registers the main thread ID for use by the IsMainThread and IsBackgroundThread functions.
void RecordMainThread()
{
_mainThreadId = GetCurrentThreadId();
}
#ifdef __cplusplus
}
#endif
#endif /* not NDEBUG */
MainPage::MainPage()
{
InitializeComponent();
Windows::UI::Color color;
color.R = 0x25;
color.G = 0x72;
color.B = 0xAC;
color.A = 0x40;
m_textcolor_brush = ref new SolidColorBrush(color);
color.R = 0xAC;
color.G = 0x72;
color.B = 0x25;
color.A = 0x40;
m_linkcolor_brush = ref new SolidColorBrush(color);
// Create the image brush
m_renderedImage = ref new ImageBrush();
m_doc = NULL;
m_content.num = 0;
CleanUp();
RecordMainThread();
// use at most 128M for resource cache
ctx = fz_new_context(NULL, NULL, 128<<20);
}
///
/// Invoked when this page is about to be displayed in a Frame.
///
/// Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
(void) e; // Unused parameter
}
void winapp::MainPage::ExitInvokedHandler(Windows::UI::Popups::IUICommand^ command)
{
}
void winapp::MainPage::OKInvokedHandler(Windows::UI::Popups::IUICommand^ command)
{
}
void winapp::MainPage::NotifyUser(String^ strMessage, NotifyType_t type)
{
MessageDialog^ msg = ref new MessageDialog(strMessage);
UICommand^ ExitCommand = nullptr;
UICommand^ OKCommand = nullptr;
switch (type)
{
case StatusMessage:
OKCommand = ref new UICommand("OK",
ref new UICommandInvokedHandler(this, &winapp::MainPage::OKInvokedHandler));
msg->Commands->Append(OKCommand);
/// Set the command that will be invoked by default
msg->DefaultCommandIndex = 0;
// Set the command to be invoked when escape is pressed
msg->CancelCommandIndex = 1;
break;
case ErrorMessage:
ExitCommand = ref new UICommand("Exit",
ref new UICommandInvokedHandler(this, &winapp::MainPage::ExitInvokedHandler));
msg->Commands->Append(ExitCommand);
/// Set the command that will be invoked by default
msg->DefaultCommandIndex = 0;
// Set the command to be invoked when escape is pressed
msg->CancelCommandIndex = 1;
break;
default:
break;
}
// Show the message dialog
msg->ShowAsync();
}
bool winapp::MainPage::EnsureUnsnapped()
{
// FilePicker APIs will not work if the application is in a snapped state.
// If an app wants to show a FilePicker while snapped, it must attempt to unsnap first
bool unsnapped = (ApplicationView::Value != ApplicationViewState::Snapped ||
ApplicationView::TryUnsnap());
if (!unsnapped)
{
NotifyUser("Cannot unsnap the application", StatusMessage);
}
return unsnapped;
}
void winapp::MainPage::Picker(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (!EnsureUnsnapped())
return;
FileOpenPicker^ openPicker = ref new FileOpenPicker();
openPicker->ViewMode = PickerViewMode::List;
openPicker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
openPicker->FileTypeFilter->Append(".pdf");
openPicker->FileTypeFilter->Append(".xps");
openPicker->FileTypeFilter->Append(".oxps");
create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
{
if (file)
{
this->OpenDocumentPrep(file);
}
else
{
/* Nothing selected */
}
});
}
void MainPage::NotifyUserFileNotExist()
{
//NotifyUser("The file '" + Filename + "' does not exist. Use scenario one to create this file.", NotifyType::ErrorMessage);
}
void MainPage::HandleFileNotFoundException(Platform::COMException^ e)
{
if (e->HResult == 0x80070002) // Catch FileNotExistException
{
NotifyUserFileNotExist();
}
else
{
throw e;
}
}
RectSize MainPage::currPageSize(int page)
{
RectSize Size;
FlipViewItem ^flipview_temp = (FlipViewItem^) m_curr_flipView->Items->GetAt(page);
Size.height = flipview_temp->ActualHeight;
Size.width = flipview_temp->ActualWidth;
return Size;
}
static RectSize measurePage(fz_document *doc, fz_page *page)
{
RectSize pageSize;
fz_rect rect;
fz_rect *bounds = fz_bound_page(doc, page, &rect);
pageSize.width = bounds->x1 - bounds->x0;
pageSize.height = bounds->y1 - bounds->y0;
return pageSize;
}
static RectSize fitPageToScreen(RectSize page, RectSize screen)
{
RectSize pageSize;
float hscale = screen.width / page.width;
float vscale = screen.height / page.height;
float scale = fz_min(hscale, vscale);
pageSize.width = floorf(page.width * scale) / page.width;
pageSize.height = floorf(page.height * scale) / page.height;
return pageSize;
}
spatial_info_t MainPage::InitSpatial(double scale)
{
spatial_info_t value;
value.size.height = this->ActualHeight;
value.size.width = this->ActualWidth;
value.scale_factor = scale;
return value;
}
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);
}
void MainPage::ReleasePages(int old_page, int new_page)
{
if (old_page == new_page) return;
/* To keep from having memory issue reset the page back to
the thumb if we are done rendering the thumbnails */
if (this->m_thumb_page_start == this->m_num_pages)
{
for (int k = old_page - LOOK_AHEAD; k <= old_page + LOOK_AHEAD; k++)
{
if (k < new_page - LOOK_AHEAD || k > new_page + LOOK_AHEAD)
{
if (k >= 0 && k < this->m_num_pages)
{
SetThumb(k);
}
}
}
}
}
void MainPage::InitThumbnails()
{
this->m_thumbnails.raster = ref new Array(m_num_pages);
this->m_thumbnails.scale = ref new Array(m_num_pages);
this->m_thumbnails.canvas_h = ref new Array