aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile2
-rw-r--r--fbpdf.c186
-rw-r--r--kbd.c71
-rw-r--r--kbd.h1
4 files changed, 220 insertions, 40 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 6066a09..a6ba6b6 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -192,7 +192,7 @@ fbi: $(OBJS_FBI) $(OBJS_READER)
# object files
OBJS_FBPDF := \
- fbpdf.o vt.o fbtools.o drmtools.o
+ fbpdf.o vt.o kbd.o fbtools.o drmtools.o
# font + drm + jpeg/exif libs
fbpdf : CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm poppler-glib)
diff --git a/fbpdf.c b/fbpdf.c
index 063f2d9..dee8c03 100644
--- a/fbpdf.c
+++ b/fbpdf.c
@@ -17,6 +17,7 @@
#include <termios.h>
#include <math.h>
#include <signal.h>
+#include <inttypes.h>
#include <ctype.h>
#include <locale.h>
#include <wchar.h>
@@ -32,6 +33,7 @@
#include <poppler.h>
#include "vt.h"
+#include "kbd.h"
#include "fbtools.h"
#include "drmtools.h"
@@ -40,9 +42,99 @@
gfxstate *gfx;
int debug;
PopplerDocument *doc;
-PopplerPage *page;
cairo_surface_t *surface;
-cairo_t *context;
+
+PopplerPage *page;
+double pw, ph; /* pdf page size */
+double scale;
+double sw, sh; /* scaled pdf page size */
+double tx, ty;
+
+/* ---------------------------------------------------------------------- */
+
+static void page_check_scroll(void)
+{
+ if (gfx->vdisplay < sh) {
+ /* range check vertical scroll */
+ if (ty < gfx->vdisplay - sh)
+ ty = gfx->vdisplay - sh;
+ if (ty > 0)
+ ty = 0;
+ } else {
+ /* no need to scroll -> center */
+ ty = (gfx->vdisplay - sh) / 2;
+ }
+
+ if (gfx->hdisplay < sw) {
+ /* range check vertical scroll */
+ if (tx < gfx->hdisplay - sw)
+ tx = gfx->hdisplay - sw;
+ if (tx > 0)
+ tx = 0;
+ } else {
+ /* no need to scroll -> center */
+ tx = (gfx->hdisplay - sw) / 2;
+ }
+}
+
+static void page_move(double dx, double dy)
+{
+ tx += dx * gfx->hdisplay;
+ ty += dy * gfx->vdisplay;
+ page_check_scroll();
+}
+
+static void page_scale(double factor)
+{
+ scale *= factor;
+ tx *= factor;
+ ty *= factor;
+ sw = pw * scale;
+ sh = ph * scale;
+ page_check_scroll();
+}
+
+static void page_fit(void)
+{
+ double sx, sy;
+
+ poppler_page_get_size(page, &pw, &ph);
+ sx = gfx->hdisplay / pw;
+ sy = gfx->vdisplay / ph;
+ scale = sx < sy ? sx : sy;
+ sw = pw * scale;
+ sh = ph * scale;
+ page_check_scroll();
+}
+
+static void page_fit_width(void)
+{
+ poppler_page_get_size(page, &pw, &ph);
+ scale = gfx->hdisplay / pw;
+ sw = pw * scale;
+ sh = ph * scale;
+ ty = 0;
+ page_check_scroll();
+}
+
+static void page_render(void)
+{
+ cairo_t *context;
+
+ context = cairo_create(surface);
+
+ cairo_set_source_rgb(context, 1, 1, 1);
+ cairo_paint(context);
+
+ cairo_translate(context, tx, ty);
+ cairo_scale(context, scale, scale);
+ poppler_page_render(page, context);
+ cairo_show_page(context);
+ cairo_destroy(context);
+
+ if (gfx->flush_display)
+ gfx->flush_display();
+}
/* ---------------------------------------------------------------------- */
@@ -93,14 +185,17 @@ static void cleanup_and_exit(int code)
static void console_switch_redraw(void)
{
- /* TODO */
+ gfx->restore_display();
}
int main(int argc, char *argv[])
{
GError *err = NULL;
bool framebuffer = false;
- double w,h;
+ bool quit, newpage;
+ char key[32];
+ uint32_t keycode, keymod;
+ int index = 0;
setlocale(LC_ALL,"");
@@ -141,19 +236,84 @@ int main(int argc, char *argv[])
gfx->hdisplay,
gfx->vdisplay,
gfx->stride);
- context = cairo_create(surface);
- cairo_set_source_rgb(context, 1, 1, 1);
- cairo_paint(context);
+ tty_raw();
- page = poppler_document_get_page(doc, 0);
- poppler_page_get_size(page, &w, &h);
- fprintf(stderr, "page: %.1lf x %.1lf\n", w, h);
+ index = 0;
+ newpage = true;
+ for (quit = false; !quit;) {
+ if (newpage) {
+ page = poppler_document_get_page(doc, index);
+ if (0)
+ page_fit();
+ if (1)
+ page_fit_width();
+ newpage = false;
+ }
+ page_render();
- poppler_page_render(page, context);
- cairo_show_page(context);
+ if (check_console_switch()) {
+ continue;
+ }
+ kbd_wait(0);
+ if (check_console_switch()) {
+ continue;
+ }
+
+ memset(key, 0, sizeof(key));
+ read(0, key, sizeof(key)-1);
+ keycode = kbd_parse(key, &keymod);
+
+ switch (keycode) {
+ case KEY_ESC:
+ case KEY_Q:
+ quit = true;
+ break;
+ case KEY_PAGEUP:
+ if (index > 0) {
+ index--;
+ newpage = true;
+ }
+ break;
+ case KEY_PAGEDOWN:
+ if (index+1 < poppler_document_get_n_pages(doc)) {
+ index++;
+ newpage = true;
+ }
+ break;
+ case KEY_UP:
+ page_move(0, 0.2);
+ break;
+ case KEY_DOWN:
+ page_move(0, -0.2);
+ break;
+ case KEY_LEFT:
+ page_move(0.2, 0);
+ break;
+ case KEY_RIGHT:
+ page_move(-0.2, 0);
+ break;
+ case KEY_KPMINUS:
+ page_scale(0.7);
+ break;
+ case KEY_KPPLUS:
+ page_scale(1.5);
+ break;
+ case KEY_SPACE:
+ if (ty > gfx->vdisplay - sh) {
+ page_move(0, -0.75);
+ break;
+ } else if (index+1 < poppler_document_get_n_pages(doc)) {
+ index++;
+ newpage = true;
+ } else {
+ quit = true;
+ }
+ break;
+ }
+ }
- sleep(5);
+ tty_restore();
cleanup_and_exit(0);
return 0;
}
diff --git a/kbd.c b/kbd.c
index d5f0191..b788607 100644
--- a/kbd.c
+++ b/kbd.c
@@ -74,31 +74,6 @@ static struct termctrl termctrl[] = {
{ .seq = "Y", .code = KEY_Y, .mod = KEY_MOD_SHIFT },
{ .seq = "Z", .code = KEY_Z, .mod = KEY_MOD_SHIFT },
- { .seq = "0", .code = KEY_0, },
- { .seq = "1", .code = KEY_1, },
- { .seq = "2", .code = KEY_2, },
- { .seq = "3", .code = KEY_3, },
- { .seq = "4", .code = KEY_4, },
- { .seq = "5", .code = KEY_5, },
- { .seq = "6", .code = KEY_6, },
- { .seq = "7", .code = KEY_7, },
- { .seq = "8", .code = KEY_8, },
- { .seq = "9", .code = KEY_9, },
-
- { .seq = "\x1b[A", .code = KEY_UP },
- { .seq = "\x1b[B", .code = KEY_DOWN },
- { .seq = "\x1b[C", .code = KEY_RIGHT },
- { .seq = "\x1b[D", .code = KEY_LEFT },
- { .seq = "\x1b[F", .code = KEY_END },
- { .seq = "\x1b[H", .code = KEY_HOME },
-
- { .seq = "\x1b[1~", .code = KEY_HOME },
- { .seq = "\x1b[2~", .code = KEY_INSERT },
- { .seq = "\x1b[3~", .code = KEY_DELETE },
- { .seq = "\x1b[4~", .code = KEY_END },
- { .seq = "\x1b[5~", .code = KEY_PAGEUP },
- { .seq = "\x1b[6~", .code = KEY_PAGEDOWN },
-
{ .seq = "\x01", .code = KEY_A, .mod = KEY_MOD_CTRL },
{ .seq = "\x02", .code = KEY_B, .mod = KEY_MOD_CTRL },
{ .seq = "\x03", .code = KEY_C, .mod = KEY_MOD_CTRL },
@@ -125,7 +100,36 @@ static struct termctrl termctrl[] = {
{ .seq = "\x18", .code = KEY_X, .mod = KEY_MOD_CTRL },
{ .seq = "\x19", .code = KEY_Y, .mod = KEY_MOD_CTRL },
{ .seq = "\x1a", .code = KEY_Z, .mod = KEY_MOD_CTRL },
- { .seq = "\x1b", .code = KEY_ESC },
+
+ { .seq = "0", .code = KEY_0 },
+ { .seq = "1", .code = KEY_1 },
+ { .seq = "2", .code = KEY_2 },
+ { .seq = "3", .code = KEY_3 },
+ { .seq = "4", .code = KEY_4 },
+ { .seq = "5", .code = KEY_5 },
+ { .seq = "6", .code = KEY_6 },
+ { .seq = "7", .code = KEY_7 },
+ { .seq = "8", .code = KEY_8 },
+ { .seq = "9", .code = KEY_9 },
+
+ { .seq = " ", .code = KEY_SPACE },
+ { .seq = "\x1b", .code = KEY_ESC },
+ { .seq = "+", .code = KEY_KPPLUS },
+ { .seq = "-", .code = KEY_KPMINUS },
+
+ { .seq = "\x1b[A", .code = KEY_UP },
+ { .seq = "\x1b[B", .code = KEY_DOWN },
+ { .seq = "\x1b[C", .code = KEY_RIGHT },
+ { .seq = "\x1b[D", .code = KEY_LEFT },
+ { .seq = "\x1b[F", .code = KEY_END },
+ { .seq = "\x1b[H", .code = KEY_HOME },
+
+ { .seq = "\x1b[1~", .code = KEY_HOME },
+ { .seq = "\x1b[2~", .code = KEY_INSERT },
+ { .seq = "\x1b[3~", .code = KEY_DELETE },
+ { .seq = "\x1b[4~", .code = KEY_END },
+ { .seq = "\x1b[5~", .code = KEY_PAGEUP },
+ { .seq = "\x1b[6~", .code = KEY_PAGEDOWN },
{ /* EOF */ }
};
@@ -144,6 +148,21 @@ uint32_t kbd_parse(const char *key, uint32_t *mod)
return KEY_RESERVED;
}
+int kbd_wait(int timeout)
+{
+ struct timeval limit;
+ fd_set set;
+ int rc;
+
+ FD_ZERO(&set);
+ FD_SET(STDIN_FILENO, &set);
+ limit.tv_sec = timeout;
+ limit.tv_usec = 0;
+ rc = select(STDIN_FILENO + 1, &set, NULL, NULL,
+ timeout ? &limit : NULL);
+ return rc;
+}
+
/* ---------------------------------------------------------------------- */
struct termios saved_attributes;
diff --git a/kbd.h b/kbd.h
index cd15fd3..86aec75 100644
--- a/kbd.h
+++ b/kbd.h
@@ -4,6 +4,7 @@
#define KEY_MOD_CTRL (1 << 1)
uint32_t kbd_parse(const char *key, uint32_t *mod);
+int kbd_wait(int timeout);
void tty_raw(void);
void tty_restore(void);