From cb334c5ded5a992979addffc6e5895324f5590cc Mon Sep 17 00:00:00 2001 From: malc Date: Sat, 6 Aug 2011 08:38:12 +0400 Subject: [PATCH] Make proportional display user configurable http://onlinelibrary.wiley.com/doi/10.1111/j.2153-3490.1961.tb00075.x/pdf --- link.c | 102 ++++++++++++++++++++++++++++++++++++++-------------------------- main.ml | 51 ++++++++++++++++++++++---------- 2 files changed, 95 insertions(+), 58 deletions(-) diff --git a/link.c b/link.c index 1dc44cf..c9ea70f 100644 --- a/link.c +++ b/link.c @@ -169,6 +169,7 @@ struct { } *texowners; int rotate; + int proportional; int needoutline; #ifdef _WIN32 @@ -632,24 +633,24 @@ static void layout (void) double zoom, w, maxw; struct pagedim *p = state.pagedims; - for (pindex = 0; pindex < state.pagedimcount; ++pindex, ++p) { - box.x0 = MIN (p->box.x0, p->box.x1); - box.y0 = MIN (p->box.y0, p->box.y1); - box.x1 = MAX (p->box.x0, p->box.x1); - box.y1 = MAX (p->box.y0, p->box.y1); - - ctm = fz_identity; - ctm = fz_concat (ctm, fz_translate (0, -box.y1)); - ctm = fz_concat (ctm, fz_rotate (p->rotate)); - box2 = fz_transform_rect (ctm, box); - w = box2.x1 - box2.x0; - maxw = MAX (w, maxw); + if (state.proportional) { + for (pindex = 0; pindex < state.pagedimcount; ++pindex, ++p) { + box.x0 = MIN (p->box.x0, p->box.x1); + box.y0 = MIN (p->box.y0, p->box.y1); + box.x1 = MAX (p->box.x0, p->box.x1); + box.y1 = MAX (p->box.y0, p->box.y1); + + ctm = fz_identity; + ctm = fz_concat (ctm, fz_translate (0, -box.y1)); + ctm = fz_concat (ctm, fz_rotate (p->rotate)); + box2 = fz_transform_rect (ctm, box); + w = box2.x1 - box2.x0; + maxw = MAX (w, maxw); + } } p = state.pagedims; for (pindex = 0; pindex < state.pagedimcount; ++pindex, ++p) { - double scale; - box.x0 = MIN (p->box.x0, p->box.x1); box.y0 = MIN (p->box.y0, p->box.y1); box.x1 = MAX (p->box.x0, p->box.x1); @@ -661,15 +662,20 @@ static void layout (void) box2 = fz_transform_rect (ctm, box); w = box2.x1 - box2.x0; - scale = w / maxw; - zoom = (state.w / w) * scale; + if (state.proportional) { + double scale = w / maxw; + zoom = (state.w / w) * scale; + } + else { + zoom = state.w / w; + } ctm = fz_identity; ctm = fz_concat (ctm, fz_translate (0, -box.y1)); ctm = fz_concat (ctm, fz_scale (zoom, -zoom)); memcpy (&p->ctm1, &ctm, sizeof (ctm)); ctm = fz_concat (ctm, fz_rotate (p->rotate)); p->bbox = fz_round_rect (fz_transform_rect (ctm, box)); - p->left = ((maxw - w) * zoom) / 2.0; + p->left = state.proportional ? ((maxw - w) * zoom) / 2.0 : 0; memcpy (&p->ctm, &ctm, sizeof (ctm)); } @@ -978,23 +984,23 @@ mainloop (void *unused) fz_obj *obj; size_t filenamelen; char *password; - char *anglestr; char *filename = p + 5; + char *p2 ; + int angle, proportional; filenamelen = strlen (filename); password = filename + filenamelen + 1; - anglestr = password + strlen (password) + 1; - - if (*anglestr) { - int angle; - int ret = sscanf (anglestr, "%d", &angle); - if (ret != 1) { - errx (1, "malformed angle `%.*s' ret=%d", - strlen (anglestr), anglestr, ret); - } - state.rotate = angle; + p2 = password + strlen (password) + 1; + + ret = sscanf (p2, " %d %d", &angle, &proportional); + if (ret != 2) { + errx (1, "malformed open `%*s' ret=%d", + len - (p2 - p), p2, ret); } + state.rotate = angle; + state.proportional = proportional; + openxref (filename, password); initpdims (); @@ -1072,16 +1078,18 @@ mainloop (void *unused) unlock ("geometry"); printd (state.sock, "C %d", state.pagecount); } - else if (!strncmp ("rotate", p, 6)) { + else if (!strncmp ("reinit", p, 6)) { float rotate; + int proportional; printd (state.sock, "c"); - ret = sscanf (p + 6, " %f", &rotate); - if (ret != 1) { + ret = sscanf (p + 6, " %f %d", &rotate, &proportional); + if (ret != 2) { errx (1, "bad rotate line `%.*s' ret=%d", len, p, ret); } - lock ("rotate"); + lock ("reinit"); state.rotate = rotate; + state.proportional = proportional; state.pagedimcount = 0; free (state.pagedims); state.pagedims = NULL; @@ -1092,7 +1100,7 @@ mainloop (void *unused) freepage (state.pig); state.pig = NULL; } - unlock ("rotate"); + unlock ("reinit"); printd (state.sock, "C %d", state.pagecount); } else if (!strncmp ("render", p, 6)) { @@ -1108,11 +1116,12 @@ mainloop (void *unused) page = render (pageno, pindex); unlock ("render"); - printd (state.sock, "r %d %d %d %d %p", + printd (state.sock, "r %d %d %d %d %d %p", pageno, state.w, state.h, state.rotate, + state.proportional, page); } else if (!strncmp ("interrupt", p, 9)) { @@ -1803,14 +1812,16 @@ CAMLprim value ml_zoom_for_height (value winw_v, value winh_v, value dw_v) goto done; } - for (i = 0, p = state.pagedims; i < state.pagedimcount; ++i, ++p) { - double x0, x1, w; + if (state.proportional) { + for (i = 0, p = state.pagedims; i < state.pagedimcount; ++i, ++p) { + double x0, x1, w; - x0 = MIN (p->box.x0, p->box.x1); - x1 = MAX (p->box.x0, p->box.x1); + x0 = MIN (p->box.x0, p->box.x1); + x1 = MAX (p->box.x0, p->box.x1); - w = x1 - x0; - maxw = MAX (w, maxw); + w = x1 - x0; + maxw = MAX (w, maxw); + } } for (i = 0, p = state.pagedims; i < state.pagedimcount; ++i, ++p) { @@ -1823,9 +1834,16 @@ CAMLprim value ml_zoom_for_height (value winw_v, value winh_v, value dw_v) w = x1 - x0; h = y1 - y0; - scale = w / maxw; - scaledh = h * scale; + if (state.proportional) { + scale = w / maxw; + scaledh = h * scale; + } + else { + scale = 1.0; + scaledh = h; + } + if (scaledh > maxh) { maxh = scaledh; ph = scaledh; diff --git a/main.ml b/main.ml index ea4a526..e2ad696 100644 --- a/main.ml +++ b/main.ml @@ -117,6 +117,7 @@ type conf = ; mutable winw : int ; mutable winh : int ; mutable savebmarks : bool + ; mutable proportional : bool } ;; @@ -138,7 +139,7 @@ type state = ; mutable ty : float ; mutable maxy : int ; mutable layout : layout list - ; pagemap : ((int * int * int), string) Hashtbl.t + ; pagemap : ((int * int * int * bool), string) Hashtbl.t ; mutable pdims : (int * int * int * int) list ; mutable pagecount : int ; pagecache : string circbuf @@ -187,6 +188,7 @@ let conf = ; winw = 900 ; winh = 900 ; savebmarks = true + ; proportional = true } ;; @@ -443,12 +445,14 @@ let clamp incr = ;; let getopaque pageno = - try Some (Hashtbl.find state.pagemap (pageno + 1, state.w, conf.angle)) + try Some (Hashtbl.find state.pagemap + (pageno + 1, state.w, conf.angle, conf.proportional)) with Not_found -> None ;; let cache pageno opaque = - Hashtbl.replace state.pagemap (pageno + 1, state.w, conf.angle) opaque + Hashtbl.replace state.pagemap + (pageno + 1, state.w, conf.angle, conf.proportional) opaque ;; let validopaque opaque = String.length opaque > 0;; @@ -724,18 +728,18 @@ let act cmd = (pageno, c, (x0, y0, x1, y1, x2, y2, x3, y3)) :: state.rects1 | 'r' -> - let n, w, h, r, p = - Scanf.sscanf cmd "r %d %d %d %d %s" - (fun n w h r p -> (n, w, h, r, p)) + let n, w, h, r, l, p = + Scanf.sscanf cmd "r %d %d %d %d %d %s" + (fun n w h r l p -> (n, w, h, r, l != 0, p)) in - Hashtbl.replace state.pagemap (n, w, r) p; + Hashtbl.replace state.pagemap (n, w, r, l) p; let opaque = cbpeekw state.pagecache in if validopaque opaque then ( let k = Hashtbl.fold (fun k v a -> if v = opaque then k else a) - state.pagemap (-1, -1, -1) + state.pagemap (-1, -1, -1, false) in wcmd "free" [`s opaque]; Hashtbl.remove state.pagemap k @@ -879,10 +883,11 @@ let textentry text key = TEcont text ;; -let rotate angle = +let reinit angle proportional = conf.angle <- angle; + conf.proportional <- proportional; invalidate (); - wcmd "rotate" [`i angle]; + wcmd "reinit" [`i angle; `b proportional]; ;; let optentry text key = @@ -906,7 +911,7 @@ let optentry text key = s (Printexc.to_string exc); None with - | Some angle -> rotate angle + | Some angle -> reinit angle conf.proportional | None -> () in TEswitch ('^', "", None, intentry, ondone) @@ -958,6 +963,10 @@ let optentry text key = in TEswitch ('%', "", None, intentry, ondone) + | 'l' -> + reinit conf.angle (not conf.proportional); + TEdone ("proprortional display " ^ btos conf.proportional) + | _ -> state.text <- Printf.sprintf "bad option %d `%c'" key c; TEstop @@ -1041,13 +1050,22 @@ let doreshape w h = Glut.reshapeWindow w h; ;; +let writeopen path password = + writecmd state.csock + ("open " ^ path ^ "\000" + ^ state.password ^ "\000" + ^ string_of_int conf.angle ^ " " + ^ (if conf.proportional then "1" else "0")) + ; +;; + let opendoc path password = invalidate (); state.path <- path; state.password <- password; Hashtbl.clear state.pagemap; - writecmd state.csock ("open " ^ path ^ "\000" ^ password ^ "\000"); + writeopen path password; Glut.setWindowTitle ("llpp " ^ Filename.basename path); wcmd "geometry" [`i state.w; `i conf.winh]; ;; @@ -1293,7 +1311,7 @@ let viewkeyboard ~key ~x ~y = end | '<' | '>' -> - rotate (conf.angle + (if c = '>' then 30 else -30)); + reinit (conf.angle + (if c = '>' then 30 else -30)) conf.proportional | '[' | ']' -> state.colorscale <- @@ -2052,6 +2070,7 @@ struct | "width" -> { c with winw = int_of_string v } | "height" -> { c with winh = int_of_string v } | "persistent-bookmarks" -> { c with savebmarks = bool_of_string v } + | "proportional-display" -> { c with proportional = bool_of_string v } | _ -> c with exn -> prerr_endline ("Error processing attribute (`" ^ @@ -2099,6 +2118,7 @@ struct dst.winw <- src.winw; dst.winh <- src.winh; dst.savebmarks <- src.savebmarks; + dst.proportional <- src.proportional; ;; let unent s = @@ -2349,6 +2369,7 @@ struct ob "presentation" c.presentation dc.presentation; oi "rotation-angle" c.angle dc.angle; ob "persistent-bookmarks" c.savebmarks dc.savebmarks; + ob "proportional-display" c.proportional dc.proportional; ;; let save () = @@ -2475,9 +2496,7 @@ let () = state.csock <- csock; state.ssock <- ssock; state.text <- "Opening " ^ path; - writecmd state.csock - ("open " ^ path ^ "\000" ^ state.password ^ "\000" - ^ string_of_int conf.angle ^ "\000"); + writeopen state.path state.password; at_exit State.save; -- 2.11.4.GIT