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 */
50 static int zoom
= 150;
51 static int zoom_def
= 150; /* default zoom */
54 static int invert
; /* invert colors? */
56 static void draw(void)
58 int bpp
= FBM_BPP(fb_mode());
60 fbval_t
*rbuf
= malloc(scols
* sizeof(rbuf
[0]));
61 for (i
= srow
; i
< srow
+ srows
; i
++) {
62 int cbeg
= MAX(scol
, pcol
);
63 int cend
= MIN(scol
+ scols
, pcol
+ pcols
);
64 memset(rbuf
, 0, scols
* sizeof(rbuf
[0]));
65 if (i
>= prow
&& i
< prow
+ prows
&& cbeg
< cend
) {
66 memcpy(rbuf
+ cbeg
- scol
,
67 pbuf
+ (i
- prow
) * pcols
+ cbeg
- pcol
,
68 (cend
- cbeg
) * sizeof(rbuf
[0]));
70 memcpy(fb_mem(i
- srow
), rbuf
, scols
* bpp
);
75 static int loadpage(int p
)
78 if (p
< 1 || p
> doc_pages(doc
))
82 pbuf
= doc_draw(doc
, p
, zoom
, rotate
, &prows
, &pcols
);
84 for (i
= 0; i
< prows
* pcols
; i
++)
85 pbuf
[i
] = pbuf
[i
] ^ 0xffffffff;
93 static void zoom_page(int z
)
96 zoom
= MIN(MAXZOOM
, MAX(1, z
));
98 srow
= srow
* zoom
/ _zoom
;
101 static void setmark(int c
)
105 mark_row
[c
] = srow
* 100 / zoom
;
109 static void jmpmark(int c
, int offset
)
113 if (ISMARK(c
) && mark
[c
]) {
115 int dst_row
= offset
? mark_row
[c
] * zoom
/ 100 : 0;
118 srow
= offset
? dst_row
: prow
;
122 static int readkey(void)
125 if (read(0, &b
, 1) <= 0)
130 static int getcount(int def
)
132 int result
= count
? count
: def
;
137 static void printinfo(void)
140 printf("FBPDF: file:%s page:%d(%d) zoom:%d%% \x1b[K\r",
141 filename
, num
, doc_pages(doc
), zoom
);
145 static void term_setup(void)
147 struct termios newtermios
;
148 tcgetattr(0, &termios
);
149 newtermios
= termios
;
150 newtermios
.c_lflag
&= ~ICANON
;
151 newtermios
.c_lflag
&= ~ECHO
;
152 tcsetattr(0, TCSAFLUSH
, &newtermios
);
153 printf("\x1b[?25l"); /* hide the cursor */
154 printf("\x1b[2J"); /* clear the screen */
158 static void term_cleanup(void)
160 tcsetattr(0, 0, &termios
);
161 printf("\x1b[?25h\n"); /* show the cursor */
164 static void sigcont(int sig
)
169 static int reload(void)
172 doc
= doc_open(filename
);
173 if (!doc
|| !doc_pages(doc
)) {
174 fprintf(stderr
, "\nfbpdf: cannot open <%s>\n", filename
);
182 static int rmargin(void)
186 for (i
= 0; i
< prows
; i
++) {
188 while (j
> ret
&& pbuf
[i
* pcols
+ j
] == FB_VAL(255, 255, 255))
196 static int lmargin(void)
200 for (i
= 0; i
< prows
; i
++) {
202 while (j
< ret
&& pbuf
[i
* pcols
+ j
] == FB_VAL(255, 255, 255))
210 static void mainloop(void)
212 int step
= srows
/ PAGESTEPS
;
213 int hstep
= scols
/ PAGESTEPS
;
216 signal(SIGCONT
, sigcont
);
221 while ((c
= readkey()) != -1) {
224 if (c
== 'e' && reload())
226 switch (c
) { /* commands that do not require redrawing */
228 numdiff
= num
- getcount(num
);
232 zoom_def
= getcount(zoom
);
248 count
= count
* 10 + c
- '0';
250 switch (c
) { /* commands that require redrawing */
253 if (!loadpage(num
+ getcount(1)))
258 if (!loadpage(num
- getcount(1)))
263 if (!loadpage(getcount(doc_pages(doc
) - numdiff
) + numdiff
))
267 numdiff
= num
- getcount(num
);
269 if (!loadpage(num
+ numdiff
))
274 zoom_page(getcount(zoom_def
));
277 zoom_page(pcols
? zoom
* scols
/ pcols
: zoom
);
280 if (lmargin() < rmargin())
281 zoom_page(zoom
* (scols
- hstep
) /
282 (rmargin() - lmargin()));
285 zoom_page(prows
? zoom
* srows
/ prows
: zoom
);
288 rotate
= getcount(0);
294 jmpmark(readkey(), c
== '`');
297 srow
+= step
* getcount(1);
300 srow
-= step
* getcount(1);
303 scol
+= hstep
* getcount(1);
306 scol
-= hstep
* getcount(1);
312 srow
= prow
+ prows
- srows
;
315 srow
= prow
+ prows
/ 2 - srows
/ 2;
322 srow
+= srows
* getcount(1) - step
;
326 srow
-= srows
* getcount(1) - step
;
332 scol
= pcol
+ pcols
- scols
;
335 scol
= pcol
+ lmargin() - hstep
/ 2;
338 scol
= pcol
+ rmargin() + hstep
/ 2 - scols
;
346 default: /* no need to redraw */
349 srow
= MAX(prow
- srows
+ MARGIN
, MIN(prow
+ prows
- MARGIN
, srow
));
350 scol
= MAX(pcol
- scols
+ MARGIN
, MIN(pcol
+ pcols
- MARGIN
, scol
));
357 "usage: fbpdf [-r rotation] [-z zoom x10] [-p page] filename";
359 int main(int argc
, char *argv
[])
366 strcpy(filename
, argv
[argc
- 1]);
367 doc
= doc_open(filename
);
368 if (!doc
|| !doc_pages(doc
)) {
369 fprintf(stderr
, "fbpdf: cannot open <%s>\n", filename
);
372 for (i
= 1; i
< argc
&& argv
[i
][0] == '-'; i
++) {
373 switch (argv
[i
][1]) {
375 rotate
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
378 zoom
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]) * 10;
381 num
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
386 if (fb_init(getenv("FBDEV")))
390 if (FBM_BPP(fb_mode()) != sizeof(fbval_t
))
391 fprintf(stderr
, "fbpdf: fbval_t doesn't match fb depth\n");