It works now! ePub files still dont work.
This commit is contained in:
parent
f55236a39b
commit
dfed263a85
|
@ -3,9 +3,9 @@
|
||||||
This is a project I've haven't worked on for a while and I'm just now getting back to it. This is a Nintendo Switch Homebrew Application and will read ePub files, or eventually, what ever MuPDF supports.
|
This is a project I've haven't worked on for a while and I'm just now getting back to it. This is a Nintendo Switch Homebrew Application and will read ePub files, or eventually, what ever MuPDF supports.
|
||||||
|
|
||||||
### Current State:
|
### Current State:
|
||||||
* Crashes your switch.
|
* ePubs cause a crash, PDFs dont load, idk what happends with other files.
|
||||||
* Just about **ALL** of the code isn't even mine but taken from an old NX-Shell repo.
|
* Just about **ALL** of the code isn't even mine but taken from an old NX-Shell repo.
|
||||||
* Working on redoing the code and making it not crash your switch.
|
* Working on redoing the code
|
||||||
|
|
||||||
### TODO:
|
### TODO:
|
||||||
* Use MuPDF.
|
* Use MuPDF.
|
||||||
|
|
Binary file not shown.
|
@ -1,10 +1,8 @@
|
||||||
#ifndef EBOOK_READER_SDL_HELPER_H
|
#ifndef EBOOK_READER_SDL_HELPER_H
|
||||||
#define EBOOK_READER_SDL_HELPER_H
|
#define EBOOK_READER_SDL_HELPER_H
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
static inline SDL_Color SDL_MakeColour(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||||
#include <SDL2/SDL_ttf.h>
|
{
|
||||||
|
|
||||||
static inline SDL_Color SDL_MakeColour(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
|
||||||
SDL_Color colour = {r, g, b, a};
|
SDL_Color colour = {r, g, b, a};
|
||||||
return colour;
|
return colour;
|
||||||
}
|
}
|
||||||
|
@ -23,15 +21,15 @@ static inline SDL_Color SDL_MakeColour(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||||
#define TEXT_MIN_COLOUR_LIGHT SDL_MakeColour(32, 32, 32, 255)
|
#define TEXT_MIN_COLOUR_LIGHT SDL_MakeColour(32, 32, 32, 255)
|
||||||
#define TEXT_MIN_COLOUR_DARK SDL_MakeColour(185, 185, 185, 255)
|
#define TEXT_MIN_COLOUR_DARK SDL_MakeColour(185, 185, 185, 255)
|
||||||
#define BAR_COLOUR SDL_MakeColour(200, 200, 200, 255)
|
#define BAR_COLOUR SDL_MakeColour(200, 200, 200, 255)
|
||||||
#define PROGRESS_COLOUR SDL_MakeColour(48, 174, 222, 255)
|
|
||||||
|
|
||||||
void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour);
|
void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour);
|
||||||
void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour);
|
void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour);
|
||||||
void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour);
|
void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour);
|
||||||
void SDL_DrawText(SDL_Surface* window_surface, TTF_Font *font, int x, int y, SDL_Color colour, const char *text);
|
void SDL_DrawText(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char *text);
|
||||||
void SDL_DrawTextf(SDL_Surface* window_surface, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...);
|
void SDL_DrawTextf(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...);
|
||||||
void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path);
|
void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path);
|
||||||
void SDL_LoadImageBuf(SDL_Renderer *renderer, SDL_Texture **texture, void *mem, int size);
|
void SDL_LoadImageBuf(SDL_Renderer *renderer, SDL_Texture **texture, void *mem, int size);
|
||||||
void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h);
|
void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y);
|
||||||
|
void SDL_DrawImageScale(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -4,10 +4,9 @@
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_ttf.h>
|
#include <SDL2/SDL_ttf.h>
|
||||||
|
|
||||||
extern SDL_Renderer* RENDERER;
|
|
||||||
extern SDL_Window *WINDOW;
|
extern SDL_Window *WINDOW;
|
||||||
extern SDL_Surface *WINDOW_SURFACE;
|
extern SDL_Surface *WINDOW_SURFACE;
|
||||||
|
extern SDL_Renderer *RENDERER;
|
||||||
extern TTF_Font *ARIAL_UNICODE;
|
extern TTF_Font *ARIAL_UNICODE;
|
||||||
extern SDL_Event EVENT;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -2,10 +2,7 @@
|
||||||
#define EBOOK_READER_MENU_BOOK_READER_H
|
#define EBOOK_READER_MENU_BOOK_READER_H
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include <SDL2/SDL_ttf.h>
|
|
||||||
|
|
||||||
//void Menu_OpenBook(SDL_Renderer *renderer, SDL_Surface* window_surface, TTF_Font *font, char *path);
|
|
||||||
void Menu_OpenBook(char *path);
|
void Menu_OpenBook(char *path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef NX_SHELL_STATUS_BAR_H
|
#ifndef EBOOK_READER_STATUS_BAR_H
|
||||||
#define NX_SHELL_STATUS_BAR_H
|
#define EBOOK_READER_STATUS_BAR_H
|
||||||
|
|
||||||
void StatusBar_DisplayTime(void);
|
void StatusBar_DisplayTime(void);
|
||||||
|
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
#include "BookReader.hpp"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "SDL_helper.h"
|
|
||||||
#include "status_bar.h"
|
|
||||||
//#include "common.h"
|
|
||||||
//#include "config.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
fz_context *ctx = NULL;
|
|
||||||
|
|
||||||
static inline void FreeTextureIfNeeded(SDL_Texture **texture) {
|
|
||||||
if (texture && *texture) {
|
|
||||||
SDL_DestroyTexture(*texture);
|
|
||||||
*texture = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BookReader::BookReader(SDL_Renderer *renderer, const char *path) {
|
|
||||||
RENDERER = renderer;
|
|
||||||
if (ctx == NULL) {
|
|
||||||
ctx = fz_new_context(NULL, NULL, 128 << 10);
|
|
||||||
fz_register_document_handlers(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
//doc = fz_open_document(ctx, path);
|
|
||||||
doc = fz_open_document_with_stream(ctx, path, fz_open_file(ctx, path));
|
|
||||||
pdf = pdf_specifics(ctx, doc);
|
|
||||||
|
|
||||||
pages_count = fz_count_pages(ctx, doc);
|
|
||||||
|
|
||||||
SDL_Rect viewport;
|
|
||||||
SDL_RenderGetViewport(renderer, &viewport);
|
|
||||||
screen_bounds = fz_make_rect(0, 0, viewport.w, viewport.h);
|
|
||||||
|
|
||||||
load_page(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BookReader::~BookReader() {
|
|
||||||
fz_drop_document(ctx, doc);
|
|
||||||
|
|
||||||
FreeTextureIfNeeded(&page_texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::previous_page() {
|
|
||||||
load_page(current_page - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::next_page() {
|
|
||||||
load_page(current_page + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::zoom_in() {
|
|
||||||
set_zoom(zoom + 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::zoom_out() {
|
|
||||||
set_zoom(zoom - 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::move_page_up() {
|
|
||||||
move_page(0, -50);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::move_page_down() {
|
|
||||||
move_page(0, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::move_page_left() {
|
|
||||||
move_page(-50, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::move_page_right() {
|
|
||||||
move_page(50, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::reset_page() {
|
|
||||||
page_center = fz_make_point(screen_bounds.x1 / 2, screen_bounds.y1 / 2);
|
|
||||||
set_zoom(min_zoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::draw(SDL_Surface *window_surface, TTF_Font *font) {
|
|
||||||
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
|
||||||
|
|
||||||
SDL_Rect rect;
|
|
||||||
rect.x = page_center.x - w / 2;
|
|
||||||
rect.y = page_center.y - h / 2;
|
|
||||||
rect.w = w;
|
|
||||||
rect.h = h;
|
|
||||||
|
|
||||||
SDL_ClearScreen(RENDERER, SDL_MakeColour(33, 39, 43, 255));
|
|
||||||
SDL_RenderClear(RENDERER);
|
|
||||||
|
|
||||||
SDL_RenderCopy(RENDERER, page_texture, NULL, &rect);
|
|
||||||
|
|
||||||
//if (--status_bar_visible_counter > 0) {
|
|
||||||
char title[128];
|
|
||||||
sprintf(title, "%i/%i, %.2f%%", current_page + 1, pages_count, zoom * 100);
|
|
||||||
|
|
||||||
int title_width = 0, title_height = 0;
|
|
||||||
TTF_SizeText(font, title, &title_width, &title_height);
|
|
||||||
|
|
||||||
SDL_Color color = STATUS_BAR_LIGHT;
|
|
||||||
|
|
||||||
SDL_DrawRect(RENDERER, 0, 0, 1920, 60, SDL_MakeColour(color.r, color.g, color.b, 128));
|
|
||||||
SDL_DrawText(window_surface, font, (screen_bounds.x1 - title_width) / 2, (44 - title_height) / 2, WHITE, title);
|
|
||||||
|
|
||||||
StatusBar_DisplayTime();
|
|
||||||
//}
|
|
||||||
|
|
||||||
SDL_RenderPresent(RENDERER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::load_page(int num) {
|
|
||||||
current_page = std::min(std::max(0, num), pages_count - 1);
|
|
||||||
|
|
||||||
fz_drop_page(ctx, page);
|
|
||||||
page = fz_load_page(ctx, doc, current_page);
|
|
||||||
|
|
||||||
fz_rect bounds;
|
|
||||||
//fz_bound_page(ctx, page, &bounds);
|
|
||||||
fz_bound_page(ctx, page);
|
|
||||||
|
|
||||||
if (page_bounds.x1 != bounds.x1 || page_bounds.y1 != bounds.y1) {
|
|
||||||
page_bounds = bounds;
|
|
||||||
page_center = fz_make_point(screen_bounds.x1 / 2, screen_bounds.y1 / 2);
|
|
||||||
|
|
||||||
min_zoom = fmin(screen_bounds.x1 / bounds.x1, screen_bounds.y1 / bounds.y1);
|
|
||||||
max_zoom = fmax(screen_bounds.x1 / bounds.x1, screen_bounds.y1 / bounds.y1);
|
|
||||||
zoom = min_zoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
render_page_to_texture();
|
|
||||||
|
|
||||||
status_bar_visible_counter = 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::render_page_to_texture() {
|
|
||||||
FreeTextureIfNeeded(&page_texture);
|
|
||||||
|
|
||||||
fz_matrix m = fz_identity;
|
|
||||||
//fz_scale(&m, zoom, zoom);
|
|
||||||
fz_scale(zoom, zoom);
|
|
||||||
|
|
||||||
fz_pixmap *pix = fz_new_pixmap_from_page_contents(ctx, page, m, fz_device_rgb(ctx), 0);
|
|
||||||
SDL_Surface *image = SDL_CreateRGBSurfaceFrom(pix->samples, pix->w, pix->h, pix->n * 8, pix->w * pix->n, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
|
|
||||||
page_texture = SDL_CreateTextureFromSurface(RENDERER, image);
|
|
||||||
|
|
||||||
SDL_FreeSurface(image);
|
|
||||||
fz_drop_pixmap(ctx, pix);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::set_zoom(float value) {
|
|
||||||
value = fmin(fmax(min_zoom, value), max_zoom);
|
|
||||||
|
|
||||||
if (value == zoom) return;
|
|
||||||
|
|
||||||
zoom = value;
|
|
||||||
|
|
||||||
load_page(current_page);
|
|
||||||
move_page(0, 0);
|
|
||||||
status_bar_visible_counter = 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BookReader::move_page(float x, float y) {
|
|
||||||
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
|
||||||
|
|
||||||
page_center.x = fmin(fmax(page_center.x + x, w / 2), screen_bounds.x1 - w / 2);
|
|
||||||
page_center.y = fmin(fmax(page_center.y + y, screen_bounds.y1 - h / 2), h / 2);
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
#ifndef EBOOK_READER_BOOK_READER_HPP
|
|
||||||
#define EBOOK_READER_BOOK_READER_HPP
|
|
||||||
|
|
||||||
#include <mupdf/pdf.h>
|
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
#include <SDL2/SDL_ttf.h>
|
|
||||||
|
|
||||||
struct SDL_Texture;
|
|
||||||
|
|
||||||
class BookReader {
|
|
||||||
public:
|
|
||||||
BookReader(SDL_Renderer *renderer, const char *path);
|
|
||||||
~BookReader();
|
|
||||||
|
|
||||||
void previous_page();
|
|
||||||
void next_page();
|
|
||||||
void zoom_in();
|
|
||||||
void zoom_out();
|
|
||||||
void move_page_up();
|
|
||||||
void move_page_down();
|
|
||||||
void move_page_left();
|
|
||||||
void move_page_right();
|
|
||||||
void reset_page();
|
|
||||||
void draw(SDL_Surface *window_surface, TTF_Font *font);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void load_page(int num);
|
|
||||||
void render_page_to_texture();
|
|
||||||
void set_zoom(float value);
|
|
||||||
void move_page(float x, float y);
|
|
||||||
|
|
||||||
fz_document *doc = NULL;
|
|
||||||
pdf_document *pdf = NULL;
|
|
||||||
fz_page *page = NULL;
|
|
||||||
fz_rect page_bounds = fz_empty_rect, screen_bounds = fz_empty_rect;
|
|
||||||
fz_point page_center = fz_make_point(0, 0);
|
|
||||||
|
|
||||||
SDL_Texture *page_texture = NULL;
|
|
||||||
SDL_Renderer *RENDERER = NULL;
|
|
||||||
|
|
||||||
int current_page = -1, pages_count = 0;
|
|
||||||
float min_zoom = 1, max_zoom = 1, zoom = 1;
|
|
||||||
|
|
||||||
int status_bar_visible_counter = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,46 +1,46 @@
|
||||||
|
#include "common.h"
|
||||||
#include "SDL_helper.h"
|
#include "SDL_helper.h"
|
||||||
|
|
||||||
void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour)
|
void SDL_ClearScreen(SDL_Renderer *renderer, SDL_Color colour) {
|
||||||
{
|
|
||||||
SDL_SetRenderDrawColor(renderer, colour.r, colour.g, colour.b, colour.a);
|
SDL_SetRenderDrawColor(renderer, colour.r, colour.g, colour.b, colour.a);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour)
|
void SDL_DrawRect(SDL_Renderer *renderer, int x, int y, int w, int h, SDL_Color colour) {
|
||||||
{
|
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
rect.x = x; rect.y = y; rect.w = w; rect.h = h;
|
rect.x = x; rect.y = y; rect.w = w; rect.h = h;
|
||||||
SDL_SetRenderDrawColor(renderer, colour.r, colour.g, colour.b, colour.a);
|
SDL_SetRenderDrawColor(RENDERER, colour.r, colour.g, colour.b, colour.a);
|
||||||
SDL_RenderFillRect(renderer, &rect);
|
SDL_RenderFillRect(RENDERER, &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour)
|
void SDL_DrawCircle(SDL_Renderer *renderer, int x, int y, int r, SDL_Color colour) {
|
||||||
{
|
|
||||||
filledCircleRGBA(renderer, x, y, r, colour.r, colour.g, colour.b, colour.a);
|
filledCircleRGBA(renderer, x, y, r, colour.r, colour.g, colour.b, colour.a);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DrawText(SDL_Surface* window_surface, TTF_Font *font, int x, int y, SDL_Color colour, const char *text)
|
void SDL_DrawText(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char *text) {
|
||||||
{
|
|
||||||
SDL_Surface *surface = TTF_RenderText_Blended_Wrapped(font, text, colour, 1280);
|
SDL_Surface *surface = TTF_RenderText_Blended_Wrapped(font, text, colour, 1280);
|
||||||
SDL_SetSurfaceAlphaMod(surface, colour.a);
|
SDL_SetSurfaceAlphaMod(surface, colour.a);
|
||||||
SDL_Rect position = {x, y, surface->w, surface->h};
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
SDL_BlitSurface(surface, NULL, window_surface, &position);
|
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
SDL_Rect position;
|
||||||
|
position.x = x; position.y = y;
|
||||||
|
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, &position);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DrawTextf(SDL_Surface* window_surface, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...)
|
void SDL_DrawTextf(SDL_Renderer *renderer, TTF_Font *font, int x, int y, SDL_Color colour, const char* text, ...) {
|
||||||
{
|
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, text);
|
va_start(args, text);
|
||||||
vsnprintf(buffer, 256, text, args);
|
vsnprintf(buffer, 256, text, args);
|
||||||
SDL_DrawText(window_surface, font, x, y, colour, buffer);
|
SDL_DrawText(renderer, font, x, y, colour, buffer);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path)
|
void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path) {
|
||||||
{
|
|
||||||
SDL_Surface *loaded_surface = NULL;
|
SDL_Surface *loaded_surface = NULL;
|
||||||
loaded_surface = IMG_Load(path);
|
loaded_surface = IMG_Load(path);
|
||||||
|
|
||||||
|
@ -54,24 +54,14 @@ void SDL_LoadImage(SDL_Renderer *renderer, SDL_Texture **texture, char *path)
|
||||||
SDL_FreeSurface(loaded_surface);
|
SDL_FreeSurface(loaded_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_LoadImageBuf(SDL_Renderer *renderer, SDL_Texture **texture, void *mem, int size)
|
void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y) {
|
||||||
{
|
SDL_Rect position;
|
||||||
SDL_Surface *loaded_surface = NULL;
|
position.x = x; position.y = y;
|
||||||
SDL_RWops *rw = SDL_RWFromMem(mem, size);
|
SDL_QueryTexture(texture, NULL, NULL, &position.w, &position.h);
|
||||||
loaded_surface = IMG_Load_RW(rw, 1);
|
SDL_RenderCopy(renderer, texture, NULL, &position);
|
||||||
|
|
||||||
if (loaded_surface)
|
|
||||||
{
|
|
||||||
Uint32 colorkey = SDL_MapRGB(loaded_surface->format, 0, 0, 0);
|
|
||||||
SDL_SetColorKey(loaded_surface, SDL_TRUE, colorkey);
|
|
||||||
*texture = SDL_CreateTextureFromSurface(renderer, loaded_surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_FreeSurface(loaded_surface);
|
void SDL_DrawImageScale(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h) {
|
||||||
}
|
|
||||||
|
|
||||||
void SDL_DrawImage(SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, int w, int h)
|
|
||||||
{
|
|
||||||
SDL_Rect position;
|
SDL_Rect position;
|
||||||
position.x = x; position.y = y; position.w = w; position.h = h;
|
position.x = x; position.y = y; position.w = w; position.h = h;
|
||||||
SDL_RenderCopy(renderer, texture, NULL, &position);
|
SDL_RenderCopy(renderer, texture, NULL, &position);
|
||||||
|
|
|
@ -76,7 +76,7 @@ void Init_Services() {
|
||||||
// available switch SDL2 video modes :
|
// available switch SDL2 video modes :
|
||||||
// 1920 x 1080 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
// 1920 x 1080 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
// 1280 x 720 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
// 1280 x 720 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
WINDOW = SDL_CreateWindow("sdl2_gles2", 0, 0, 1920, 1080, 0);
|
WINDOW = SDL_CreateWindow("sdl2_gles2", 0, 0, 1280, 720, 0);
|
||||||
if (!WINDOW) {
|
if (!WINDOW) {
|
||||||
SDL_Log("SDL_CreateWindow: %s\n", SDL_GetError());
|
SDL_Log("SDL_CreateWindow: %s\n", SDL_GetError());
|
||||||
Term_Services();
|
Term_Services();
|
||||||
|
@ -95,7 +95,7 @@ void Init_Services() {
|
||||||
|
|
||||||
romfsInit();
|
romfsInit();
|
||||||
|
|
||||||
ARIAL_UNICODE = TTF_OpenFont("romfs:/arial-unicode-ms.ttf", 30);
|
ARIAL_UNICODE = TTF_OpenFont("romfs:/arial.ttf", 35);
|
||||||
if (!ARIAL_UNICODE) {
|
if (!ARIAL_UNICODE) {
|
||||||
Term_Services();
|
Term_Services();
|
||||||
}
|
}
|
||||||
|
@ -122,20 +122,15 @@ int main(int argc, char *argv[]) {
|
||||||
Init_Services();
|
Init_Services();
|
||||||
|
|
||||||
std::cout << "Opening test.epub" << std::endl;
|
std::cout << "Opening test.epub" << std::endl;
|
||||||
Menu_OpenBook("/switch/eBookReader/books/test.pdf");
|
Menu_OpenBook("/switch/eBookReader/books/test.epub");
|
||||||
//Menu_OpenBook("/switch/eBookReader/books/test.epub");
|
//Menu_OpenBook("/switch/eBookReader/books/test.epub");
|
||||||
|
|
||||||
while (run) {
|
while (run) {
|
||||||
while (SDL_PollEvent(&EVENT)) {
|
while (SDL_PollEvent(&EVENT)) {
|
||||||
switch (EVENT.type) {
|
switch (EVENT.type) {
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
SDL_Log("Joystick %d axis %d value: %d\n",
|
|
||||||
EVENT.jaxis.which,
|
|
||||||
EVENT.jaxis.axis, EVENT.jaxis.value);
|
|
||||||
break;
|
break;
|
||||||
case SDL_JOYBUTTONDOWN:
|
case SDL_JOYBUTTONDOWN:
|
||||||
SDL_Log("Joystick %d button %d down\n",
|
|
||||||
EVENT.jbutton.which, EVENT.jbutton.button);
|
|
||||||
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L52
|
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L52
|
||||||
// seek for joystick #0
|
// seek for joystick #0
|
||||||
if (EVENT.jbutton.which == 0) {
|
if (EVENT.jbutton.which == 0) {
|
||||||
|
@ -158,56 +153,6 @@ int main(int argc, char *argv[]) {
|
||||||
SDL_RenderPresent(RENDERER);*/
|
SDL_RenderPresent(RENDERER);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*while (!done) {
|
|
||||||
while (SDL_PollEvent(&EVENT)) {
|
|
||||||
switch (EVENT.type) {
|
|
||||||
case SDL_JOYAXISMOTION:
|
|
||||||
SDL_Log("Joystick %d axis %d value: %d\n",
|
|
||||||
EVENT.jaxis.which,
|
|
||||||
EVENT.jaxis.axis, EVENT.jaxis.value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_JOYBUTTONDOWN:
|
|
||||||
SDL_Log("Joystick %d button %d down\n",
|
|
||||||
EVENT.jbutton.which, EVENT.jbutton.button);
|
|
||||||
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L52
|
|
||||||
// seek for joystick #0
|
|
||||||
if (EVENT.jbutton.which == 0) {
|
|
||||||
if (EVENT.jbutton.button == 0) {
|
|
||||||
// (A) button down
|
|
||||||
} else if (EVENT.jbutton.button == 10) {
|
|
||||||
// (+) button down
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
// fill window bounds
|
|
||||||
SDL_SetRenderDrawColor(renderer, 111, 111, 111, 255);
|
|
||||||
SDL_GetWindowSize(window, &w, &h);
|
|
||||||
SDL_Rect f = {0, 0, w, h};
|
|
||||||
SDL_RenderFillRect(renderer, &f);
|
|
||||||
|
|
||||||
draw_rects(renderer, x, 0);
|
|
||||||
draw_rects(renderer, x, h - 64);
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
|
||||||
|
|
||||||
x++;
|
|
||||||
if (x > w - 192) {
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
//SDL_Renderer *renderer, SDL_Surface* window_surface, TTF_Font *font, char *path
|
|
||||||
|
|
||||||
Term_Services();
|
Term_Services();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "menu_book_reader.h"
|
|
||||||
#include "common.h"
|
|
||||||
//#include "touch_helper.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "BookReader.hpp"
|
|
||||||
|
|
||||||
extern SDL_Renderer* RENDERER;
|
|
||||||
extern SDL_Window* WINDOW;
|
|
||||||
extern SDL_Surface* WINDOW_SURFACE;
|
|
||||||
|
|
||||||
void Menu_OpenBook(char *path) {
|
|
||||||
BookReader *reader = new BookReader(RENDERER, path);
|
|
||||||
|
|
||||||
/*TouchInfo touchInfo;
|
|
||||||
Touch_Init(&touchInfo);*/
|
|
||||||
|
|
||||||
while(appletMainLoop()) {
|
|
||||||
reader->draw(WINDOW_SURFACE, ARIAL_UNICODE);
|
|
||||||
|
|
||||||
hidScanInput();
|
|
||||||
//Touch_Process(&touchInfo);
|
|
||||||
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
|
||||||
u64 kHeld = hidKeysHeld(CONTROLLER_P1_AUTO);
|
|
||||||
|
|
||||||
if ((kDown & KEY_B) || (kDown & KEY_PLUS)) {
|
|
||||||
std::cout << "B | PLUS" << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((kDown & KEY_DLEFT) || (kDown & KEY_L)) {
|
|
||||||
std::cout << "B | LEFT" << std::endl;
|
|
||||||
reader->previous_page();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((kDown & KEY_DRIGHT) || (kDown & KEY_R)) {
|
|
||||||
std::cout << "B | RIGHT" << std::endl;
|
|
||||||
reader->next_page();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kDown & KEY_LSTICK) {
|
|
||||||
std::cout << "B | LEFT STICK KEY" << std::endl;
|
|
||||||
reader->reset_page();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_DUP) {
|
|
||||||
std::cout << "B | UP" << std::endl;
|
|
||||||
reader->zoom_in();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_DDOWN) {
|
|
||||||
std::cout << "B | DOWN" << std::endl;
|
|
||||||
reader->zoom_out();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_LSTICK_UP) {
|
|
||||||
std::cout << "B | LEFT STICK UP" << std::endl;
|
|
||||||
reader->move_page_up();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_LSTICK_DOWN) {
|
|
||||||
std::cout << "B | LEFT STICK DOWN" << std::endl;
|
|
||||||
reader->move_page_down();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_LSTICK_LEFT) {
|
|
||||||
std::cout << "B | LEFT STICK LEFT" << std::endl;
|
|
||||||
reader->move_page_left();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kHeld & KEY_LSTICK_RIGHT) {
|
|
||||||
std::cout << "B | LEFT STICK RIGHT" << std::endl;
|
|
||||||
reader->move_page_right();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone)
|
|
||||||
{
|
|
||||||
if (tapped_inside(touchInfo, 0, 0, 120, 720))
|
|
||||||
reader->previous_page();
|
|
||||||
else if (tapped_inside(touchInfo, 1160, 0, 1280, 720))
|
|
||||||
reader->next_page();
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
delete reader;
|
|
||||||
}
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
#include "BookReader.hpp"
|
||||||
|
#include "PageLayout.hpp"
|
||||||
|
#include "LandscapePageLayout.hpp"
|
||||||
|
#include "common.h"
|
||||||
|
#include <algorithm>
|
||||||
|
//#include <libconfig.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "SDL_helper.h"
|
||||||
|
#include "status_bar.h"
|
||||||
|
//#include "config.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
fz_context *ctx = NULL;
|
||||||
|
/*config_t *config = NULL;
|
||||||
|
|
||||||
|
static int load_last_page(const char *book_name) {
|
||||||
|
if (!config) {
|
||||||
|
config = (config_t *)malloc(sizeof(config_t));
|
||||||
|
config_init(config);
|
||||||
|
config_read_file(config, "/switch/NX-Shell/last_book_pages.cfg");
|
||||||
|
}
|
||||||
|
|
||||||
|
config_setting_t *setting = config_setting_get_member(config_root_setting(config), book_name);
|
||||||
|
|
||||||
|
if (setting) {
|
||||||
|
return config_setting_get_int(setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void save_last_page(const char *book_name, int current_page) {
|
||||||
|
config_setting_t *setting = config_setting_get_member(config_root_setting(config), book_name);
|
||||||
|
|
||||||
|
if (!setting) {
|
||||||
|
setting = config_setting_add(config_root_setting(config), book_name, CONFIG_TYPE_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setting) {
|
||||||
|
config_setting_set_int(setting, current_page);
|
||||||
|
config_write_file(config, "/switch/NX-Shell/last_book_pages.cfg");
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
BookReader::BookReader(const char *path) {
|
||||||
|
if (ctx == NULL) {
|
||||||
|
ctx = fz_new_context(NULL, NULL, 128 << 10);
|
||||||
|
fz_register_document_handlers(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
book_name = std::string(path).substr(std::string(path).find_last_of("/\\") + 1);
|
||||||
|
|
||||||
|
std::string invalid_chars = " :/?#[]@!$&'()*+,;=.";
|
||||||
|
for (char& c: invalid_chars) {
|
||||||
|
book_name.erase(std::remove(book_name.begin(), book_name.end(), c), book_name.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = fz_open_document(ctx, path);
|
||||||
|
|
||||||
|
//int current_page = load_last_page(book_name.c_str());
|
||||||
|
int current_page = 0;
|
||||||
|
switch_current_page_layout(_currentPageLayout, current_page);
|
||||||
|
|
||||||
|
if (current_page > 0) {
|
||||||
|
show_status_bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BookReader::~BookReader() {
|
||||||
|
fz_drop_document(ctx, doc);
|
||||||
|
|
||||||
|
delete layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::previous_page(int n) {
|
||||||
|
layout->previous_page(n);
|
||||||
|
show_status_bar();
|
||||||
|
//save_last_page(book_name.c_str(), layout->current_page());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::next_page(int n) {
|
||||||
|
layout->next_page(n);
|
||||||
|
show_status_bar();
|
||||||
|
//save_last_page(book_name.c_str(), layout->current_page());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::zoom_in() {
|
||||||
|
layout->zoom_in();
|
||||||
|
show_status_bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::zoom_out() {
|
||||||
|
layout->zoom_out();
|
||||||
|
show_status_bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::move_page_up() {
|
||||||
|
layout->move_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::move_page_down() {
|
||||||
|
layout->move_down();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::move_page_left() {
|
||||||
|
layout->move_left();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::move_page_right() {
|
||||||
|
layout->move_right();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::reset_page() {
|
||||||
|
layout->reset();
|
||||||
|
show_status_bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::switch_page_layout() {
|
||||||
|
switch (_currentPageLayout) {
|
||||||
|
case BookPageLayoutPortrait:
|
||||||
|
switch_current_page_layout(BookPageLayoutLandscape, 0);
|
||||||
|
break;
|
||||||
|
case BookPageLayoutLandscape:
|
||||||
|
switch_current_page_layout(BookPageLayoutPortrait, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::draw() {
|
||||||
|
/*if (config_dark_theme == true)
|
||||||
|
SDL_ClearScreen(RENDERER, SDL_MakeColour(33, 39, 43, 255));
|
||||||
|
else */
|
||||||
|
SDL_ClearScreen(RENDERER, SDL_MakeColour(255, 255, 255, 255));
|
||||||
|
|
||||||
|
SDL_RenderClear(RENDERER);
|
||||||
|
|
||||||
|
layout->draw_page();
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
if (--status_bar_visible_counter > 0) {
|
||||||
|
char *title = layout->info();
|
||||||
|
|
||||||
|
int title_width = 0, title_height = 0;
|
||||||
|
//TTF_SizeText(Roboto, title, &title_width, &title_height);
|
||||||
|
TTF_SizeText(ARIAL_UNICODE, title, &title_width, &title_height);
|
||||||
|
|
||||||
|
//SDL_Color color = config_dark_theme ? STATUS_BAR_DARK : STATUS_BAR_LIGHT;
|
||||||
|
SDL_Color color = STATUS_BAR_LIGHT;
|
||||||
|
|
||||||
|
SDL_DrawRect(RENDERER, 0, 0, 1280, 40, SDL_MakeColour(color.r, color.g, color.b , 128));
|
||||||
|
//SDL_DrawText(RENDERER, Roboto, (1280 - title_width) / 2, (44 - title_height) / 2, WHITE, title);
|
||||||
|
SDL_DrawText(RENDERER, ARIAL_UNICODE, (1280 - title_width) / 2, (44 - title_height) / 2, WHITE, title);
|
||||||
|
|
||||||
|
StatusBar_DisplayTime();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_RenderPresent(RENDERER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::show_status_bar() {
|
||||||
|
status_bar_visible_counter = 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BookReader::switch_current_page_layout(BookPageLayout bookPageLayout, int current_page) {
|
||||||
|
if (layout) {
|
||||||
|
current_page = layout->current_page();
|
||||||
|
delete layout;
|
||||||
|
layout = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentPageLayout = bookPageLayout;
|
||||||
|
|
||||||
|
switch (bookPageLayout) {
|
||||||
|
case BookPageLayoutPortrait:
|
||||||
|
layout = new PageLayout(doc, current_page);
|
||||||
|
break;
|
||||||
|
case BookPageLayoutLandscape:
|
||||||
|
layout = new LandscapePageLayout(doc, current_page);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef EBOOK_READER_BOOK_READER_HPP
|
||||||
|
#define EBOOK_READER_BOOK_READER_HPP
|
||||||
|
|
||||||
|
#include <mupdf/pdf.h>
|
||||||
|
#include <string>
|
||||||
|
#include "PageLayout.hpp"
|
||||||
|
|
||||||
|
struct SDL_Texture;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BookPageLayoutPortrait,
|
||||||
|
BookPageLayoutLandscape
|
||||||
|
} BookPageLayout;
|
||||||
|
|
||||||
|
class BookReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BookReader(const char *path);
|
||||||
|
~BookReader();
|
||||||
|
|
||||||
|
void previous_page(int n);
|
||||||
|
void next_page(int n);
|
||||||
|
void zoom_in();
|
||||||
|
void zoom_out();
|
||||||
|
void move_page_up();
|
||||||
|
void move_page_down();
|
||||||
|
void move_page_left();
|
||||||
|
void move_page_right();
|
||||||
|
void reset_page();
|
||||||
|
void switch_page_layout();
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
BookPageLayout currentPageLayout()
|
||||||
|
{
|
||||||
|
return _currentPageLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void show_status_bar();
|
||||||
|
void switch_current_page_layout(BookPageLayout bookPageLayout, int current_page);
|
||||||
|
|
||||||
|
fz_document *doc = NULL;
|
||||||
|
int status_bar_visible_counter = 0;
|
||||||
|
|
||||||
|
BookPageLayout _currentPageLayout = BookPageLayoutPortrait;
|
||||||
|
PageLayout *layout = NULL;
|
||||||
|
|
||||||
|
std::string book_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include "LandscapePageLayout.hpp"
|
||||||
|
#include "common.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
LandscapePageLayout::LandscapePageLayout(fz_document *doc, int current_page):PageLayout(doc, current_page)
|
||||||
|
{
|
||||||
|
int w = viewport.w;
|
||||||
|
viewport.w = viewport.h;
|
||||||
|
viewport.h = w;
|
||||||
|
|
||||||
|
render_page_to_texture(_current_page, true);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandscapePageLayout::reset()
|
||||||
|
{
|
||||||
|
page_center = fz_make_point(viewport.h / 2, viewport.w / 2);
|
||||||
|
set_zoom(min_zoom);
|
||||||
|
};
|
||||||
|
|
||||||
|
void LandscapePageLayout::draw_page()
|
||||||
|
{
|
||||||
|
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.y = page_center.y - h / 2;
|
||||||
|
rect.x = page_center.x - w / 2;
|
||||||
|
rect.w = w;
|
||||||
|
rect.h = h;
|
||||||
|
|
||||||
|
SDL_RenderCopyEx(RENDERER, page_texture, NULL, &rect, 90, NULL, SDL_FLIP_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LandscapePageLayout::move_page(float x, float y)
|
||||||
|
{
|
||||||
|
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
||||||
|
|
||||||
|
page_center.x = fmin(fmax(page_center.x + y, h / 2), viewport.h - h / 2);
|
||||||
|
page_center.y = fmin(fmax(page_center.y + x, viewport.w - w / 2), w / 2);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef EBOOK_READER_LANDSCAPE_PAGE_LAYOUT_HPP
|
||||||
|
#define EBOOK_READER_LANDSCAPE_PAGE_LAYOUT_HPP
|
||||||
|
|
||||||
|
#include "PageLayout.hpp"
|
||||||
|
|
||||||
|
class LandscapePageLayout: public PageLayout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LandscapePageLayout(fz_document *doc, int current_page);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void draw_page();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void move_page(float x, float y);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,127 @@
|
||||||
|
#include "PageLayout.hpp"
|
||||||
|
#include "common.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
PageLayout::PageLayout(fz_document *doc, int current_page):doc(doc),pdf(pdf_specifics(ctx, doc)),pages_count(fz_count_pages(ctx, doc))
|
||||||
|
{
|
||||||
|
_current_page = std::min(std::max(0, current_page), pages_count - 1);
|
||||||
|
|
||||||
|
SDL_RenderGetViewport(RENDERER, &viewport);
|
||||||
|
render_page_to_texture(_current_page, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::previous_page(int n)
|
||||||
|
{
|
||||||
|
render_page_to_texture(_current_page - n, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::next_page(int n)
|
||||||
|
{
|
||||||
|
render_page_to_texture(_current_page + n, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::zoom_in()
|
||||||
|
{
|
||||||
|
set_zoom(zoom + 0.1);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::zoom_out()
|
||||||
|
{
|
||||||
|
set_zoom(zoom - 0.1);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::move_up()
|
||||||
|
{
|
||||||
|
move_page(0, 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::move_down()
|
||||||
|
{
|
||||||
|
move_page(0, -50);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::move_left()
|
||||||
|
{
|
||||||
|
move_page(-50, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::move_right()
|
||||||
|
{
|
||||||
|
move_page(50, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::reset()
|
||||||
|
{
|
||||||
|
page_center = fz_make_point(viewport.w / 2, viewport.h / 2);
|
||||||
|
set_zoom(min_zoom);
|
||||||
|
};
|
||||||
|
|
||||||
|
void PageLayout::draw_page()
|
||||||
|
{
|
||||||
|
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
||||||
|
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = page_center.x - w / 2;
|
||||||
|
rect.y = page_center.y - h / 2;
|
||||||
|
rect.w = w;
|
||||||
|
rect.h = h;
|
||||||
|
|
||||||
|
SDL_RenderCopy(RENDERER, page_texture, NULL, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* PageLayout::info()
|
||||||
|
{
|
||||||
|
static char title[128];
|
||||||
|
sprintf(title, "%i/%i, %.2f%%", _current_page + 1, pages_count, zoom * 100);
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::render_page_to_texture(int num, bool reset_zoom)
|
||||||
|
{
|
||||||
|
FreeTextureIfNeeded(&page_texture);
|
||||||
|
|
||||||
|
_current_page = std::min(std::max(0, num), pages_count - 1);
|
||||||
|
|
||||||
|
fz_page *page = fz_load_page(ctx, doc, _current_page);
|
||||||
|
fz_rect bounds = fz_bound_page(ctx, page);
|
||||||
|
|
||||||
|
if (page_bounds.x1 != bounds.x1 || page_bounds.y1 != bounds.y1 || reset_zoom)
|
||||||
|
{
|
||||||
|
page_bounds = bounds;
|
||||||
|
page_center = fz_make_point(viewport.w / 2, viewport.h / 2);
|
||||||
|
|
||||||
|
min_zoom = fmin(viewport.w / bounds.x1, viewport.h / bounds.y1);
|
||||||
|
max_zoom = fmax(viewport.w / bounds.x1, viewport.h / bounds.y1);
|
||||||
|
zoom = min_zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
fz_pixmap *pix = fz_new_pixmap_from_page_contents(ctx, page, fz_scale(zoom, zoom), fz_device_rgb(ctx), 0);
|
||||||
|
SDL_Surface *image = SDL_CreateRGBSurfaceFrom(pix->samples, pix->w, pix->h, pix->n * 8, pix->w * pix->n, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);
|
||||||
|
page_texture = SDL_CreateTextureFromSurface(RENDERER, image);
|
||||||
|
|
||||||
|
SDL_FreeSurface(image);
|
||||||
|
fz_drop_pixmap(ctx, pix);
|
||||||
|
|
||||||
|
fz_drop_page(ctx, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::set_zoom(float value)
|
||||||
|
{
|
||||||
|
value = fmin(fmax(min_zoom, value), max_zoom);
|
||||||
|
|
||||||
|
if (value == zoom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
zoom = value;
|
||||||
|
|
||||||
|
render_page_to_texture(_current_page, false);
|
||||||
|
move_page(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageLayout::move_page(float x, float y)
|
||||||
|
{
|
||||||
|
float w = page_bounds.x1 * zoom, h = page_bounds.y1 * zoom;
|
||||||
|
|
||||||
|
page_center.x = fmin(fmax(page_center.x + x, w / 2), viewport.w - w / 2);
|
||||||
|
page_center.y = fmin(fmax(page_center.y + y, viewport.h - h / 2), h / 2);
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef EBOOK_READER_PAGE_LAYOUT_HPP
|
||||||
|
#define EBOOK_READER_PAGE_LAYOUT_HPP
|
||||||
|
|
||||||
|
#include <mupdf/pdf.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
extern fz_context *ctx;
|
||||||
|
|
||||||
|
static inline void FreeTextureIfNeeded(SDL_Texture **texture)
|
||||||
|
{
|
||||||
|
if (texture && *texture)
|
||||||
|
{
|
||||||
|
SDL_DestroyTexture(*texture);
|
||||||
|
*texture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PageLayout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PageLayout(fz_document *doc, int current_page);
|
||||||
|
|
||||||
|
int current_page()
|
||||||
|
{
|
||||||
|
return _current_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void previous_page(int n);
|
||||||
|
virtual void next_page(int n);
|
||||||
|
virtual void zoom_in();
|
||||||
|
virtual void zoom_out();
|
||||||
|
virtual void move_up();
|
||||||
|
virtual void move_down();
|
||||||
|
virtual void move_left();
|
||||||
|
virtual void move_right();
|
||||||
|
virtual void reset();
|
||||||
|
virtual void draw_page();
|
||||||
|
virtual char* info();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void render_page_to_texture(int num, bool reset_zoom);
|
||||||
|
virtual void set_zoom(float value);
|
||||||
|
virtual void move_page(float x, float y);
|
||||||
|
|
||||||
|
fz_document *doc = NULL;
|
||||||
|
pdf_document *pdf = NULL;
|
||||||
|
const int pages_count = 0;
|
||||||
|
|
||||||
|
int _current_page = 0;
|
||||||
|
fz_rect page_bounds = fz_empty_rect;
|
||||||
|
fz_point page_center = fz_make_point(0, 0);
|
||||||
|
float min_zoom = 1, max_zoom = 1, zoom = 1;
|
||||||
|
|
||||||
|
SDL_Rect viewport;
|
||||||
|
SDL_Texture *page_texture = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,121 @@
|
||||||
|
extern "C" {
|
||||||
|
#include "menu_book_reader.h"
|
||||||
|
#include "common.h"
|
||||||
|
//#include "touch_helper.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "BookReader.hpp"
|
||||||
|
|
||||||
|
void Menu_OpenBook(char *path) {
|
||||||
|
BookReader *reader = new BookReader(path);
|
||||||
|
|
||||||
|
/*TouchInfo touchInfo;
|
||||||
|
Touch_Init(&touchInfo);*/
|
||||||
|
|
||||||
|
while(appletMainLoop()) {
|
||||||
|
reader->draw();
|
||||||
|
|
||||||
|
hidScanInput();
|
||||||
|
|
||||||
|
//Touch_Process(&touchInfo);
|
||||||
|
|
||||||
|
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
|
||||||
|
u64 kHeld = hidKeysHeld(CONTROLLER_P1_AUTO);
|
||||||
|
|
||||||
|
if (kDown & KEY_DLEFT) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode()))
|
||||||
|
reader->previous_page(1);
|
||||||
|
else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode()))
|
||||||
|
reader->zoom_out();
|
||||||
|
} else if (kDown & KEY_DRIGHT) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode()))
|
||||||
|
reader->next_page(1);
|
||||||
|
else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode()))
|
||||||
|
reader->zoom_in();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDown & KEY_R) {
|
||||||
|
reader->next_page(10);
|
||||||
|
} else if (kDown & KEY_L) {
|
||||||
|
reader->previous_page(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((kDown & KEY_DUP) || (kHeld & KEY_RSTICK_UP)) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->zoom_in();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->previous_page(1);
|
||||||
|
}
|
||||||
|
//reader->reset_page();
|
||||||
|
} else if ((kDown & KEY_DDOWN) || (kHeld & KEY_RSTICK_DOWN)) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->zoom_out();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->next_page(1);
|
||||||
|
}
|
||||||
|
//reader->reset_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kHeld & KEY_LSTICK_UP) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->move_page_up();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->move_page_left();
|
||||||
|
}
|
||||||
|
} else if (kHeld & KEY_LSTICK_DOWN) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->move_page_down();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->move_page_right();
|
||||||
|
}
|
||||||
|
} else if (kHeld & KEY_LSTICK_LEFT) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->move_page_left();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->move_page_up();
|
||||||
|
}
|
||||||
|
} else if (kHeld & KEY_LSTICK_RIGHT) {
|
||||||
|
if (reader->currentPageLayout() == BookPageLayoutPortrait || (!hidGetHandheldMode())) {
|
||||||
|
reader->move_page_right();
|
||||||
|
} else if ((reader->currentPageLayout() == BookPageLayoutLandscape) && (hidGetHandheldMode())) {
|
||||||
|
reader->move_page_down();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDown & KEY_B) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDown & KEY_LSTICK || kDown & KEY_RSTICK) {
|
||||||
|
reader->reset_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kDown & KEY_Y) {
|
||||||
|
reader->switch_page_layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (touchInfo.state == TouchEnded && touchInfo.tapType != TapNone)
|
||||||
|
{
|
||||||
|
float tapRegion = 120;
|
||||||
|
|
||||||
|
switch (reader->currentPageLayout())
|
||||||
|
{
|
||||||
|
case BookPageLayoutPortrait:
|
||||||
|
if (tapped_inside(touchInfo, 0, 0, tapRegion, 720))
|
||||||
|
reader->previous_page(1);
|
||||||
|
else if (tapped_inside(touchInfo, 1280 - tapRegion, 0, 1280, 720))
|
||||||
|
reader->next_page(1);
|
||||||
|
break;
|
||||||
|
case BookPageLayoutLandscape:
|
||||||
|
if (tapped_inside(touchInfo, 0, 0, 1280, tapRegion))
|
||||||
|
reader->previous_page(1);
|
||||||
|
else if (tapped_inside(touchInfo, 0, 720 - tapRegion, 1280, 720))
|
||||||
|
reader->next_page(1);
|
||||||
|
reader->reset_page();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
delete reader;
|
||||||
|
}
|
|
@ -4,20 +4,21 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "SDL_helper.h"
|
#include "SDL_helper.h"
|
||||||
#include "status_bar.h"
|
#include "status_bar.h"
|
||||||
|
#include "textures.h"
|
||||||
|
|
||||||
static char *Clock_GetCurrentTime(bool _12hour) {
|
static char *Clock_GetCurrentTime(void)
|
||||||
|
{
|
||||||
static char buffer[10];
|
static char buffer[10];
|
||||||
|
|
||||||
u64 current_time;
|
time_t unixTime = time(NULL);
|
||||||
timeGetCurrentTime(TimeType_UserSystemClock, ¤t_time);
|
struct tm* timeStruct = gmtime((const time_t *)&unixTime);
|
||||||
struct tm* time_struct = gmtime((const time_t *)¤t_time);
|
int hours = (timeStruct->tm_hour);
|
||||||
int hours = time_struct->tm_hour;
|
int minutes = timeStruct->tm_min;
|
||||||
int minutes = time_struct->tm_min;
|
|
||||||
int amOrPm = 0;
|
bool amOrPm = false;
|
||||||
|
|
||||||
if (_12hour) {
|
|
||||||
if (hours < 12)
|
if (hours < 12)
|
||||||
amOrPm = 1;
|
amOrPm = true;
|
||||||
if (hours == 0)
|
if (hours == 0)
|
||||||
hours = 12;
|
hours = 12;
|
||||||
else if (hours > 12)
|
else if (hours > 12)
|
||||||
|
@ -27,14 +28,92 @@ static char *Clock_GetCurrentTime(bool _12hour) {
|
||||||
snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM");
|
snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM");
|
||||||
else
|
else
|
||||||
snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM");
|
snprintf(buffer, 10, "%2i:%02i %s", hours, minutes, amOrPm ? "AM" : "PM");
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBar_DisplayTime(void) {
|
static void StatusBar_GetBatteryStatus(int x, int y)
|
||||||
int width = 0, height = 0;
|
{
|
||||||
TTF_SizeText(ARIAL_UNICODE, Clock_GetCurrentTime(true), &width, &height);
|
u32 percent = 0;
|
||||||
|
ChargerType state;
|
||||||
|
int width = 0;
|
||||||
|
char buf[5];
|
||||||
|
|
||||||
SDL_DrawText(WINDOW_SURFACE, ARIAL_UNICODE, 1900 - width, (40 - height)/2, WHITE, Clock_GetCurrentTime(true));
|
if (R_FAILED(psmGetChargerType(&state)))
|
||||||
|
state = 0;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(psmGetBatteryChargePercentage(&percent)))
|
||||||
|
{
|
||||||
|
if (percent < 20)
|
||||||
|
SDL_DrawImage(RENDERER, battery_low, x, 3);
|
||||||
|
else if ((percent >= 20) && (percent < 30))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_20_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_20, x, 3);
|
||||||
|
}
|
||||||
|
else if ((percent >= 30) && (percent < 50))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_50_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_50, x, 3);
|
||||||
|
}
|
||||||
|
else if ((percent >= 50) && (percent < 60))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_50_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_50, x, 3);
|
||||||
|
}
|
||||||
|
else if ((percent >= 60) && (percent < 80))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_60_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_60, x, 3);
|
||||||
|
}
|
||||||
|
else if ((percent >= 80) && (percent < 90))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_80_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_80, x, 3);
|
||||||
|
}
|
||||||
|
else if ((percent >= 90) && (percent < 100))
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_90_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_90, x, 3);
|
||||||
|
}
|
||||||
|
else if (percent == 100)
|
||||||
|
{
|
||||||
|
if (state != 0)
|
||||||
|
SDL_DrawImage(RENDERER, battery_full_charging, x, 3);
|
||||||
|
else
|
||||||
|
SDL_DrawImage(RENDERER, battery_full, x, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buf, 5, "%d%%", percent);
|
||||||
|
TTF_SizeText(Roboto, buf, &width, NULL);
|
||||||
|
SDL_DrawText(RENDERER, Roboto, (x - width - 10), y, WHITE, buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(buf, 5, "%d%%", percent);
|
||||||
|
TTF_SizeText(Roboto, buf, &width, NULL);
|
||||||
|
SDL_DrawText(RENDERER, Roboto, (x - width - 10), y, WHITE, buf);
|
||||||
|
SDL_DrawImage(RENDERER, battery_unknown, x, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusBar_DisplayTime(void)
|
||||||
|
{
|
||||||
|
int width = 0, height = 0;
|
||||||
|
TTF_SizeText(Roboto, Clock_GetCurrentTime(), &width, &height);
|
||||||
|
|
||||||
|
StatusBar_GetBatteryStatus(1260 - width - 44, (40 - height) / 2);
|
||||||
|
SDL_DrawText(RENDERER, Roboto, 1260 - width, (40 - height) / 2, WHITE, Clock_GetCurrentTime());
|
||||||
}
|
}
|
Loading…
Reference in New Issue