start fbpdf git repo
[fbpdf.git] / fbpdf.c
blob81e447509dd354d4ec16bd5285f97045552086ae
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <pty.h>
7 #include <cairo/cairo.h>
8 #include <glib/poppler.h>
9 #include "draw.h"
11 #define PAGESTEPS 8
12 #define CTRLKEY(x) ((x) - 96)
13 #define MAXAREA 2
15 static PopplerDocument *doc;
16 static PopplerPage *page;
17 static int num;
18 static cairo_t *cairo;
19 static cairo_surface_t *surface;
20 static int zoom = 15;
21 static int head;
22 static int left;
23 static int count;
25 static void draw()
27 unsigned char *img = cairo_image_surface_get_data(surface);
28 fbval_t slice[1 << 14];
29 int i, j;
30 int h = MIN(fb_rows(), cairo_image_surface_get_height(surface));
31 int w = MIN(fb_cols(), cairo_image_surface_get_width(surface));
32 int cols = cairo_image_surface_get_width(surface);
33 for (i = head; i < h + head; i++) {
34 for (j = left; j < w + left; j++) {
35 unsigned char *p = img + (i * cols + j) * 4;
36 slice[j - left] = fb_color(*p, *(p + 1), *(p + 2));
38 fb_set(i - head, 0, slice, w);
42 static int load_document(char *filename)
44 char abspath[PATH_MAX];
45 char uri[PATH_MAX + 16];
46 realpath(filename, abspath);
47 snprintf(uri, sizeof(uri), "file://%s", abspath);
48 doc = poppler_document_new_from_file(uri, NULL, NULL);
49 return !doc;
52 static void cleanup_page(void)
54 if (cairo)
55 cairo_destroy(cairo);
56 if (surface)
57 cairo_surface_destroy(surface);
58 if (page)
59 g_object_unref(G_OBJECT(page));
62 static void showpage(int p)
64 cleanup_page();
65 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
66 fb_cols() * MAXAREA, fb_rows() * MAXAREA);
67 cairo = cairo_create(surface);
68 cairo_scale(cairo, (float) zoom / 10, (float) zoom / 10);
69 cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0);
70 cairo_paint(cairo);
71 if (p < 0 || p >= poppler_document_get_n_pages(doc))
72 return;
73 num = p;
74 page = poppler_document_get_page(doc, p);
75 poppler_page_render(page, cairo);
76 head = 0;
77 left = 0;
78 draw();
81 static int readkey(void)
83 char b;
84 if (read(STDIN_FILENO, &b, 1) <= 0)
85 return -1;
86 return b;
89 static int getcount(int def)
91 int result = count ? count : def;
92 count = 0;
93 return result;
96 static void mainloop()
98 int step = fb_rows() / PAGESTEPS;
99 int hstep = fb_cols() / PAGESTEPS;
100 struct termios oldtermios, termios;
101 int maxhead, maxleft;
102 int c;
103 tcgetattr(STDIN_FILENO, &termios);
104 oldtermios = termios;
105 cfmakeraw(&termios);
106 tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios);
107 showpage(0);
108 while ((c = readkey()) != -1) {
109 maxhead = cairo_image_surface_get_height(surface) - fb_rows();
110 maxleft = cairo_image_surface_get_height(surface) - fb_cols();
111 switch (c) {
112 case 'j':
113 head += step * getcount(1);
114 break;
115 case 'k':
116 head -= step * getcount(1);
117 break;
118 case 'l':
119 left += hstep * getcount(1);
120 break;
121 case 'h':
122 left -= hstep * getcount(1);
123 break;
124 case 'H':
125 head = 0;
126 break;
127 case 'L':
128 head = maxhead;
129 break;
130 case 'M':
131 head = maxhead / 2;
132 break;
133 case ' ':
134 head += fb_rows() * getcount(1) - step;
135 break;
136 case '\b':
137 head -= fb_rows() * getcount(1) - step;
138 break;
139 case CTRLKEY('f'):
140 case 'J':
141 showpage(num + getcount(1));
142 break;
143 case CTRLKEY('b'):
144 case 'K':
145 showpage(num - getcount(1));
146 break;
147 case 'G':
148 showpage(getcount(0));
149 break;
150 case 'z':
151 zoom = getcount(15);
152 showpage(num);
153 break;
154 case 'q':
155 tcsetattr(STDIN_FILENO, 0, &oldtermios);
156 return;
157 case 27:
158 count = 0;
159 break;
160 default:
161 if (isdigit(c))
162 count = count * 10 + c - '0';
164 head = MAX(0, MIN(maxhead, head));
165 left = MAX(0, MIN(maxleft, left));
166 draw();
170 int main(int argc, char* argv[])
172 if (argc < 2) {
173 printf("usage: fbpdf filename\n");
174 return 1;
176 g_type_init();
177 if (load_document(argv[1])) {
178 printf("cannot open file\n");
179 return 1;
181 fb_init();
182 mainloop();
183 cleanup_page();
184 fb_free();
185 if (doc)
186 g_object_unref(G_OBJECT(doc));
187 return 0;