2 * FBPDF LINUX FRAMEBUFFER PDF VIEWER
4 * Copyright (C) 2009-2016 Ali Gholami Rudi <ali at rudi dot ir>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 #define MIN(a, b) ((a) < (b) ? (a) : (b))
29 #define MAX(a, b) ((a) > (b) ? (a) : (b))
34 #define CTRLKEY(x) ((x) - 96)
35 #define ISMARK(x) (isalpha(x) || (x) == '\'' || (x) == '`')
37 static struct doc
*doc
;
38 static fbval_t
*pbuf
; /* current page */
39 static int srows
, scols
; /* screen dimentions */
40 static int prows
, pcols
; /* current page dimensions */
41 static int prow
, pcol
; /* page position */
42 static int srow
, scol
; /* screen position */
44 static struct termios termios
;
45 static char filename
[256];
46 static int mark
[128]; /* mark page number */
47 static int mark_row
[128]; /* mark head position */
48 static int num
= 1; /* page number */
49 static int numdiff
; /* G command page number difference */
51 static int zoom_def
= 15; /* default zoom */
54 static int invert
; /* invert colors? */
56 static void draw(void)
59 fbval_t
*rbuf
= malloc(scols
* sizeof(rbuf
[0]));
60 for (i
= srow
; i
< srow
+ srows
; i
++) {
61 int cbeg
= MAX(scol
, pcol
);
62 int cend
= MIN(scol
+ scols
, pcol
+ pcols
);
63 memset(rbuf
, 0, scols
* sizeof(rbuf
[0]));
64 if (i
>= prow
&& i
< prow
+ prows
&& cbeg
< cend
) {
65 memcpy(rbuf
+ cbeg
- scol
,
66 pbuf
+ (i
- prow
) * pcols
+ cbeg
- pcol
,
67 (cend
- cbeg
) * sizeof(rbuf
[0]));
69 fb_set(i
- srow
, 0, rbuf
, scols
);
74 static int loadpage(int p
)
77 if (p
< 1 || p
> doc_pages(doc
))
81 pbuf
= doc_draw(doc
, p
, zoom
, rotate
, &prows
, &pcols
);
83 for (i
= 0; i
< prows
* pcols
; i
++)
84 pbuf
[i
] = pbuf
[i
] ^ 0xffffffff;
92 static void zoom_page(int z
)
95 zoom
= MIN(MAXZOOM
, MAX(1, z
));
97 srow
= srow
* zoom
/ _zoom
;
100 static void setmark(int c
)
104 mark_row
[c
] = srow
/ zoom
;
108 static void jmpmark(int c
, int offset
)
112 if (ISMARK(c
) && mark
[c
]) {
114 int dst_row
= offset
? mark_row
[c
] * zoom
: 0;
117 srow
= offset
? dst_row
: prow
;
121 static int readkey(void)
124 if (read(0, &b
, 1) <= 0)
129 static int getcount(int def
)
131 int result
= count
? count
: def
;
136 static void printinfo(void)
139 printf("FBPDF: file:%s page:%d(%d) zoom:%d%% \x1b[K\r",
140 filename
, num
, doc_pages(doc
), zoom
* 10);
144 static void term_setup(void)
146 struct termios newtermios
;
147 tcgetattr(0, &termios
);
148 newtermios
= termios
;
149 newtermios
.c_lflag
&= ~ICANON
;
150 newtermios
.c_lflag
&= ~ECHO
;
151 tcsetattr(0, TCSAFLUSH
, &newtermios
);
152 printf("\x1b[?25l"); /* hide the cursor */
153 printf("\x1b[2J"); /* clear the screen */
157 static void term_cleanup(void)
159 tcsetattr(0, 0, &termios
);
160 printf("\x1b[?25h\n"); /* show the cursor */
163 static void sigcont(int sig
)
168 static int reload(void)
171 doc
= doc_open(filename
);
172 if (!doc
|| !doc_pages(doc
)) {
173 fprintf(stderr
, "\nfbpdf: cannot open <%s>\n", filename
);
181 static int rmargin(void)
185 for (i
= 0; i
< prows
; i
++) {
187 while (j
> ret
&& pbuf
[i
* pcols
+ j
] == FB_VAL(255, 255, 255))
195 static int lmargin(void)
199 for (i
= 0; i
< prows
; i
++) {
201 while (j
< ret
&& pbuf
[i
* pcols
+ j
] == FB_VAL(255, 255, 255))
209 static void mainloop(void)
211 int step
= srows
/ PAGESTEPS
;
212 int hstep
= scols
/ PAGESTEPS
;
215 signal(SIGCONT
, sigcont
);
220 while ((c
= readkey()) != -1) {
223 if (c
== 'e' && reload())
225 switch (c
) { /* commands that do not require redrawing */
227 numdiff
= num
- getcount(num
);
230 zoom_def
= getcount(zoom
);
246 count
= count
* 10 + c
- '0';
248 switch (c
) { /* commands that require redrawing */
251 if (!loadpage(num
+ getcount(1)))
256 if (!loadpage(num
- getcount(1)))
261 if (!loadpage(getcount(doc_pages(doc
) - numdiff
) + numdiff
))
265 numdiff
= num
- getcount(num
);
267 if (!loadpage(num
+ numdiff
))
271 zoom_page(getcount(zoom_def
));
274 zoom_page(pcols
? zoom
* scols
/ pcols
: zoom
);
277 if (lmargin() < rmargin())
278 zoom_page(zoom
* (scols
- hstep
) /
279 (rmargin() - lmargin()));
282 zoom_page(prows
? zoom
* srows
/ prows
: zoom
);
285 rotate
= getcount(0);
291 jmpmark(readkey(), c
== '`');
294 srow
+= step
* getcount(1);
297 srow
-= step
* getcount(1);
300 scol
+= hstep
* getcount(1);
303 scol
-= hstep
* getcount(1);
309 srow
= prow
+ prows
- srows
;
312 srow
= prow
+ prows
/ 2 - srows
/ 2;
319 srow
+= srows
* getcount(1) - step
;
323 srow
-= srows
* getcount(1) - step
;
329 scol
= pcol
+ pcols
- scols
;
332 scol
= pcol
+ lmargin() - hstep
/ 2;
335 scol
= pcol
+ rmargin() + hstep
/ 2 - scols
;
343 default: /* no need to redraw */
346 srow
= MAX(prow
- srows
+ MARGIN
, MIN(prow
+ prows
- MARGIN
, srow
));
347 scol
= MAX(pcol
- scols
+ MARGIN
, MIN(pcol
+ pcols
- MARGIN
, scol
));
354 "usage: fbpdf [-r rotation] [-z zoom x10] [-p page] filename\n";
356 int main(int argc
, char *argv
[])
363 strcpy(filename
, argv
[argc
- 1]);
364 doc
= doc_open(filename
);
365 if (!doc
|| !doc_pages(doc
)) {
366 fprintf(stderr
, "fbpdf: cannot open <%s>\n", filename
);
369 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
370 switch (argv
[i
][1]) {
372 rotate
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
375 zoom
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
378 num
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
387 if (FBM_BPP(fb_mode()) != sizeof(fbval_t
))
388 fprintf(stderr
, "fbpdf: fbval_t doesn't match fb depth\n");