2 * fbpdf - A small framebuffer pdf viewer using poppler
4 * Copyright (C) 2009 Ali Gholami Rudi
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License, as published by the
8 * Free Software Foundation.
18 #include <cairo/cairo.h>
19 #include <glib/poppler.h>
23 #define CTRLKEY(x) ((x) - 96)
27 static PopplerDocument
*doc
;
28 static PopplerPage
*page
;
30 static cairo_t
*cairo
;
31 static cairo_surface_t
*surface
;
32 static struct termios termios
;
33 static char filename
[PATH_MAX
];
41 unsigned char *img
= cairo_image_surface_get_data(surface
);
42 fbval_t slice
[1 << 14];
44 int h
= MIN(fb_rows(), cairo_image_surface_get_height(surface
));
45 int w
= MIN(fb_cols(), cairo_image_surface_get_width(surface
));
46 int cols
= cairo_image_surface_get_width(surface
);
47 for (i
= head
; i
< h
+ head
; i
++) {
48 for (j
= left
; j
< w
+ left
; j
++) {
49 unsigned char *p
= img
+ (i
* cols
+ j
) * 4;
50 slice
[j
- left
] = fb_color(*(p
+ 2), *(p
+ 1), *p
);
52 fb_set(i
- head
, 0, slice
, w
);
56 static int load_document(void)
58 char abspath
[PATH_MAX
];
59 char uri
[PATH_MAX
+ 16];
60 realpath(filename
, abspath
);
61 snprintf(uri
, sizeof(uri
), "file://%s", abspath
);
62 doc
= poppler_document_new_from_file(uri
, NULL
, NULL
);
66 static void cleanup_page(void)
71 cairo_surface_destroy(surface
);
73 g_object_unref(G_OBJECT(page
));
76 static void showpage(int p
)
78 if (p
< 0 || p
>= poppler_document_get_n_pages(doc
))
81 surface
= cairo_image_surface_create(CAIRO_FORMAT_ARGB32
,
82 fb_cols() * MAXWIDTH
, fb_rows() * MAXHEIGHT
);
83 cairo
= cairo_create(surface
);
84 cairo_scale(cairo
, (float) zoom
/ 10, (float) zoom
/ 10);
85 cairo_set_source_rgb(cairo
, 1.0, 1.0, 1.0);
88 page
= poppler_document_get_page(doc
, p
);
89 poppler_page_render(page
, cairo
);
94 static int readkey(void)
97 if (read(STDIN_FILENO
, &b
, 1) <= 0)
102 static int getcount(int def
)
104 int result
= count
? count
: def
;
109 static void printinfo(void)
112 printf("FBPDF: file:%s page:%d(%d) zoom:%d%% \x1b[K",
113 filename
, num
+ 1, poppler_document_get_n_pages(doc
), zoom
* 10);
117 static void term_setup(void)
119 struct termios newtermios
;
120 tcgetattr(STDIN_FILENO
, &termios
);
121 newtermios
= termios
;
122 newtermios
.c_lflag
&= ~ICANON
;
123 newtermios
.c_lflag
&= ~ECHO
;
124 tcsetattr(STDIN_FILENO
, TCSAFLUSH
, &newtermios
);
127 static void term_cleanup(void)
129 tcsetattr(STDIN_FILENO
, 0, &termios
);
132 static void sigcont(int sig
)
137 static void mainloop()
139 int step
= fb_rows() / PAGESTEPS
;
140 int hstep
= fb_cols() / PAGESTEPS
;
143 signal(SIGCONT
, sigcont
);
145 while ((c
= readkey()) != -1) {
146 int maxhead
= cairo_image_surface_get_height(surface
) - fb_rows();
147 int maxleft
= cairo_image_surface_get_width(surface
) - fb_cols();
151 showpage(num
+ getcount(1));
155 showpage(num
- getcount(1));
158 showpage(getcount(poppler_document_get_n_pages(doc
)) - 1);
175 count
= count
* 10 + c
- '0';
179 head
+= step
* getcount(1);
182 head
-= step
* getcount(1);
185 left
+= hstep
* getcount(1);
188 left
-= hstep
* getcount(1);
201 head
+= fb_rows() * getcount(1) - step
;
205 head
-= fb_rows() * getcount(1) - step
;
210 /* no need to redraw */
213 head
= MAX(0, MIN(maxhead
, head
));
214 left
= MAX(0, MIN(maxleft
, left
));
219 int main(int argc
, char* argv
[])
221 char *hide
= "\x1b[?25l";
222 char *show
= "\x1b[?25h";
223 char *clear
= "\x1b[2J";
225 printf("usage: fbpdf filename\n");
229 strcpy(filename
, argv
[1]);
230 if (load_document()) {
231 printf("cannot open file\n");
234 if (poppler_document_get_n_pages(doc
)) {
235 write(STDIN_FILENO
, hide
, strlen(hide
));
236 write(STDOUT_FILENO
, clear
, strlen(clear
));
242 write(STDIN_FILENO
, show
, strlen(show
));
245 printf("zero pages!\n");
249 g_object_unref(G_OBJECT(doc
));