2 external init
: Unix.file_descr
-> unit = "ml_init";;
3 external draw
: int -> int -> int -> int -> string -> unit = "ml_draw";;
4 external preload
: string -> unit = "ml_preload";;
5 (* external layout : int -> unit = "ml_layout";; *)
8 { mutable csock
: Unix.file_descr
9 ; mutable ssock
: Unix.file_descr
14 ; mutable layout
: (int * int * int * int * int * int * int) list
15 ; pixcache
: ((int * int * int), string) Hashtbl.t
16 ; mutable pages
: 'a list
17 ; mutable pagecount
: int
19 ; mutable lruidx
: int
31 ; pixcache
= Hashtbl.create
10
34 ; lru
= Array.create
12 ""
40 let log fmt
= Printf.kprintf prerr_endline fmt
;;
41 let dolog fmt
= Printf.kprintf prerr_endline fmt
;;
44 let len = String.length s
in
46 let b = Buffer.create
n in
47 Buffer.add_char
b (Char.chr
((len lsr 24) land 0xff));
48 Buffer.add_char
b (Char.chr
((len lsr 16) land 0xff));
49 Buffer.add_char
b (Char.chr
((len lsr 8) land 0xff));
50 Buffer.add_char
b (Char.chr
((len lsr 0) land 0xff));
51 Buffer.add_string
b s
;
52 let s'
= Buffer.contents
b in
53 let n'
= Unix.write fd
s'
0 n in
54 if n'
!= n then failwith
"write failed";
59 let n = Unix.read fd
s 0 4 in
60 if n != 4 then failwith
"incomplete read(len)";
62 lor (Char.code
s.[0] lsl 24)
63 lor (Char.code
s.[1] lsl 16)
64 lor (Char.code
s.[2] lsl 8)
65 lor (Char.code
s.[3] lsl 0)
67 let s = String.create
len in
68 let n = Unix.read fd
s 0 len in
69 if n != len then failwith
"incomplete read(data)";
74 let b = Buffer.create
10 in
75 Buffer.add_string
b s;
76 let rec combine = function
77 | [] -> Buffer.contents
b
79 Buffer.add_char
b ' '
;
83 | `i i
-> string_of_int i
84 | `f f
-> string_of_float f
85 | `I f
-> string_of_int
(truncate f
)
87 Buffer.add_string
b s;
91 writecmd state.csock
s;
95 let rec f pagenum pindex prev vy py dy l accu
=
96 if pagenum
= state.pagecount
99 let ((_
, w
, h
) as curr
), rest
, pindex
=
101 | ((pagenum'
, _
, _
) as curr
) :: rest
when pagenum'
= pagenum
->
102 (* log "pagenum=%d(%d) index=%d" pagenum pagenum' pindex; *)
103 curr
, rest
, pindex
+ 1
107 let pagenum'
= pagenum + 1 in
115 let e = pagenum, pindex
, w
, h
, dy
, py'
, vh in
116 (* log "lay1[%d,%d] %dx%d" pagenum pindex w h; *)
119 let e = pagenum, pindex
, w
, h
, dy
, py'
, vh in
120 let accu = e :: accu in
121 (* log "lay2[%d,%d] %dx%d" pagenum pindex w h; *)
122 f pagenum' pindex curr
(vy
+ vh) (py + h
) (dy
+ vh) rest
accu
124 f pagenum' pindex curr vy
(py + h
) dy rest
accu
126 let accu = f 0 ~
-1 (0,0,0) y
0 0 state.pages
[] in
134 GlDraw.viewport
0 0 w h
;
135 GlMat.mode `modelview
;
136 GlMat.load_identity
();
137 GlMat.mode `projection
;
138 GlMat.load_identity
();
139 GlMat.rotate ~x
:1.0 ~angle
:180.0 ();
140 GlMat.translate ~x
:~
-.1.0 ~y
:~
-.1.0 ();
141 GlMat.scale3
(2.0 /. float state.w
, 2.0 /. float state.h
, 1.0);
143 wcmd "geometry" [`i w
; `i h
];
144 let pages = layout state.y
state.h
in
145 state.layout <- pages;
146 Glut.postRedisplay
();
147 log "reshape %dx%d" w h
;
153 let n = Scanf.sscanf cmd
"C %d" (fun n -> n) in
154 state.pagecount
<- n;
155 let pages = layout state.y
state.h
in
156 state.layout <- pages;
157 Glut.postRedisplay
();
164 Scanf.sscanf cmd
"r %d %d %d %s"
165 (fun n w h p
-> (n, w
, h
, p
))
167 Hashtbl.replace
state.pixcache
(n, w
, h
) p
;
168 let idx = state.lruidx
mod (Array.length
state.lru
) in
169 let s = state.lru
.(idx) in
170 if String.length
s != 0
174 let l = Hashtbl.fold
(fun k
s' a
->
175 if s = s'
then k
:: a
else a
) state.pixcache
[]
179 Hashtbl.remove
state.pixcache k
) l;
181 state.lru
.(idx) <- p
;
182 state.lruidx
<- state.lruidx
+ 1;
183 Glut.postRedisplay
();
186 let n = Scanf.sscanf cmd
"m %d" (fun n -> n) in
190 let n = Scanf.sscanf cmd
"u %d" (fun n -> n) in
191 let s = Hashtbl.find
state.pixcache
(n, state.w
, state.h
) in
192 Hashtbl.replace
state.pixcache
(n, state.w
, state.h
) s
195 let (n, w
, h
) as pagelayout
=
196 Scanf.sscanf cmd
"l %d %d %d" (fun n w h
-> n, w
, h
)
199 (* then state.pages <- []; *)
200 state.pages <- pagelayout
:: state.pages
203 log "unknown cmd `%S'" cmd
207 ((pageno
, pindex
, pagewidth
, pageheight
, screeny
, pageyoffset
, screenheight
) as page
) =
208 let key = (pageno
+ 1, state.w
, state.h
) in
210 let pixmap = Hashtbl.find
state.pixcache
key in
212 String.length
pixmap = 0
219 log "preload render %d" pageno
;
220 Hashtbl.add
state.pixcache
key "";
221 wcmd "render" [`i
(pageno
+ 1)
229 let r, _
, _
= Unix.select
[state.csock
] [] [] 0.01 in
235 let pages = layout (state.y
+ state.h) h in
236 List.iter
preload pages;
240 let cmd = readcmd state.csock
in
246 let y = state.y + incr
in
248 let y = min
y state.maxy
in
252 let keyboard ~
key ~x ~
y =
253 begin match Char.chr
key with
254 | '
\027'
| 'q'
-> exit
0
256 begin match List.rev
state.layout with
258 | (_
, _
, _
, h, _
, pyo
, sh
) :: _
->
261 let pages = layout state.y state.h in
262 state.layout <- pages;
263 Glut.postRedisplay
();
267 begin match state.layout with
269 | (_
, _
, w
, h, _
, _
, _
) :: _
->
270 Glut.reshapeWindow w
h
274 begin match state.layout with
276 | (_
, _
, _
, h, _
, _
, sh
) :: _
->
278 let pages = layout state.y state.h in
279 state.layout <- pages;
280 Glut.postRedisplay
();
284 Glut.postRedisplay
();
287 let special ~
key ~x ~
y =
289 | Glut.KEY_LEFT
-> ()
290 | Glut.KEY_RIGHT
-> ()
291 | Glut.KEY_UP
-> clamp ~
-aincr
292 | Glut.KEY_DOWN
-> clamp aincr
293 | Glut.KEY_PAGE_UP
-> clamp (-state.h)
294 | Glut.KEY_PAGE_DOWN
-> clamp state.h
295 | Glut.KEY_HOME
-> state.y <- 0
296 | Glut.KEY_END
-> state.y <- state.maxy
- state.h
299 let pages = layout state.y state.h in
300 state.layout <- pages;
301 Glut.postRedisplay
();
316 let drawplaceholder (pageno
, pindex
, pagewidth
, pageheight
,
317 screeny
, pageyoffset
, screenheight
) =
318 GlDraw.color
(0.0, 0.0, 0.0);
319 GlDraw.begins `quads
;
320 GlDraw.vertex2
(0.0, float screeny
);
321 GlDraw.vertex2
(float pagewidth
, float screeny
);
322 GlDraw.vertex2
(float pagewidth
, float (screeny
+ screenheight
));
323 GlDraw.vertex2
(0.0, float (screeny
+ screenheight
));
327 let now () = Unix.gettimeofday
();;
330 ((pageno
, pindex
, pagewidth
, pageheight
, screeny
, pageyoffset
, screenheight
) as page
) =
331 let key = (pageno
+ 1, state.w
, state.h) in
333 let pixmap = Hashtbl.find
state.pixcache
key in
335 String.length
pixmap = 0
339 GlDraw.color
(1.0, 1.0, 1.0);
341 draw screeny pagewidth screenheight pageyoffset
pixmap;
350 Hashtbl.add
state.pixcache
key "";
351 drawplaceholder page
;
352 wcmd "render" [`i
(pageno
+ 1)
361 GlClear.color
(0.5, 0.5, 0.5) ~alpha
:0.0;
362 GlClear.clear
[`color
];
363 GlDraw.color
(0.0, 0.0, 0.0);
364 ignore
(List.fold_left
drawpage 0 (state.layout));
377 let _ = Glut.init
Sys.argv
in
378 let () = Glut.initDisplayMode ~depth
:false ~double_buffer
:true () in
379 let () = Glut.initWindowSize
w h in
380 let _ = Glut.createWindow
"lpdf (press 'h' to get help)" in
382 let csock, ssock
= Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 in
386 state.csock <- csock;
387 state.ssock
<- ssock
;
389 if Array.length
Sys.argv
= 1
390 then "/home/malc/x/inc/Info_PT_Sans.pdf"
393 writecmd csock ("open " ^
name ^
"\000");
394 (* writecmd csock "open /home/malc/x/doc/cell/CBE_Handbook_v1.1_24APR2007_pub.pdf\000"; *)
395 (* writecmd csock "box 1"; *)
397 let () = Glut.displayFunc
display in
398 let () = Glut.reshapeFunc
reshape in
399 let () = Glut.keyboardFunc
keyboard in
400 let () = Glut.specialFunc
special in
401 let () = Glut.idleFunc
(Some
idle) in
402 (* let () = Glut.mouseFunc mouse in *)
403 (* let () = Glut.motionFunc motion in *)