1+
2+ #include " view/ebook_view.hpp"
3+
4+ #ifdef USE_MUPDF
5+
6+ #include " api/http.hpp"
7+ #include < mupdf/fitz.h>
8+
9+ class fz_error : public std ::exception {
10+ public:
11+ explicit fz_error (fz_context* ctx) : ctx(ctx) {}
12+ const char * what () const noexcept override { return ctx->error .message ; }
13+
14+ private:
15+ fz_context* ctx;
16+ };
17+
18+ using namespace brls ::literals;
19+
20+ EBookView::EBookView () {
21+ this ->left = new brls::Image ();
22+ this ->left ->setFreeTexture (false );
23+ this ->left ->setFocusable (true );
24+ this ->left ->setHideHighlight (true );
25+ this ->left ->setMaxWidthPercentage (50 );
26+ this ->left ->setHideHighlightBackground (true );
27+ this ->left ->setMarginRight (10 );
28+ this ->right = new brls::Image ();
29+ this ->right ->setFreeTexture (false );
30+ this ->right ->setFocusable (true );
31+ this ->right ->setHideHighlight (true );
32+ this ->right ->setMaxWidthPercentage (50 );
33+ this ->right ->setHideHighlightBackground (true );
34+ this ->addView (this ->left );
35+ this ->addView (this ->right );
36+ this ->setJustifyContent (brls::JustifyContent::CENTER);
37+ this ->setAlignItems (brls::AlignItems::CENTER);
38+ this ->setPaddingLeft (brls::getStyle ().getMetric (" main/content_padding_sides" ));
39+ this ->setPaddingRight (brls::getStyle ().getMetric (" main/content_padding_sides" ));
40+ this ->setPaddingTop (10 .f );
41+ this ->setPaddingBottom (10 .f );
42+
43+ this ->ctx = fz_new_context (nullptr , nullptr , FZ_STORE_DEFAULT);
44+ fz_register_document_handlers (ctx);
45+
46+ this ->registerAction (" hints/back" _i18n, brls::BUTTON_B,
47+ [this ](brls::View* view) { return brls::Application::popActivity (brls::TransitionAnimation::NONE); });
48+
49+ this ->left ->registerAction (" main/player/prev" _i18n, brls::BUTTON_LB, [this ](brls::View* view) {
50+ if (this ->page <= 0 ) return false ;
51+ this ->render (this ->right , --this ->page );
52+ this ->render (this ->left , --this ->page );
53+ return true ;
54+ });
55+
56+ this ->right ->registerAction (" main/player/next" _i18n, brls::BUTTON_RB, [this ](brls::View* view) {
57+ if (this ->page >= this ->count - 1 ) return false ;
58+ this ->render (this ->left , ++this ->page );
59+ this ->render (this ->right , ++this ->page );
60+ return true ;
61+ });
62+
63+ this ->addGestureRecognizer (
64+ new brls::TapGestureRecognizer ([this ](brls::TapGestureStatus status, brls::Sound* soundToPlay) {
65+ if (status.state == brls::GestureState::END) {
66+ auto frame = this ->getFrame ();
67+ if (status.position .x < frame.getMidX ()) {
68+ this ->render (this ->right , --this ->page );
69+ this ->render (this ->left , --this ->page );
70+ } else {
71+ this ->render (this ->left , ++this ->page );
72+ this ->render (this ->right , ++this ->page );
73+ }
74+ }
75+ }));
76+ }
77+
78+ EBookView::~EBookView () {
79+ if (this ->doc ) fz_drop_document (this ->ctx , this ->doc );
80+ if (this ->ctx ) fz_drop_context (this ->ctx );
81+ }
82+
83+ void EBookView::open (const std::string& url, float percent) {
84+ this ->page = std::floor (percent);
85+
86+ ASYNC_RETAIN
87+ brls::async ([ASYNC_TOKEN, url]() {
88+ try {
89+ std::string content = HTTP::get (url, HTTP::Timeout{});
90+ fz_stream* stream = fz_open_memory (ctx, (const uint8_t *)content.data (), content.size ());
91+ fz_try (ctx) this ->doc = fz_open_document_with_stream (ctx, url.c_str (), stream);
92+ fz_always (ctx) fz_drop_stream (ctx, stream);
93+ fz_catch (ctx) throw fz_error (ctx);
94+
95+ fz_try (ctx) this ->count = fz_count_pages (ctx, this ->doc );
96+ fz_catch (ctx) throw fz_error (ctx);
97+
98+ brls::sync ([ASYNC_TOKEN]() {
99+ ASYNC_RELEASE
100+ this ->render (this ->left , this ->page );
101+ this ->render (this ->right , this ->page + 1 );
102+ });
103+ } catch (const std::exception& ex) {
104+ std::string msg = ex.what ();
105+ brls::sync ([ASYNC_TOKEN, msg]() {
106+ ASYNC_RELEASE
107+ this ->dismiss ([msg]() { brls::Application::notify (msg); });
108+ });
109+ }
110+ });
111+ }
112+
113+ void EBookView::render (brls::Image* view, int n) {
114+ if (n <= 0 || n >= this ->count ) {
115+ view->clear ();
116+ return ;
117+ }
118+ fz_pixmap* pix = nullptr ;
119+ fz_matrix ctm = fz_scale (1 .5f , 1 .5f );
120+ fz_try (ctx) pix = fz_new_pixmap_from_page_number (ctx, doc, n, ctm, fz_device_rgb (ctx), 1 );
121+ fz_catch (ctx) return ;
122+ auto vg = brls::Application::getNVGContext ();
123+ int tex = nvgCreateImageRGBA (vg, pix->w , pix->h , 0 , pix->samples );
124+ fz_drop_pixmap (ctx, pix);
125+ view->innerSetImage (tex);
126+ view->setBackgroundColor (nvgRGB (245 , 246 , 247 ));
127+ }
128+
129+ #endif
0 commit comments