open Graphics ;;
let fodder = ref 0 ;;

let draw_integer ?retval:(rv=fodder) x0 y n0 r =
  (* 7-seg display *)
  let n = ref n0 in
  let size = Math.ln_b 10 n0 in
  let len = r/3 in
  let offset = size*(len*11/7)/2 in
  for i = 0 to size do
      let x = x0 + offset - i*(len*11/7) in
      if Array.mem (!n mod 10) [|0; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x-len/2 + !(Csts.camx), y+len + !(Csts.camy)); (x-len/2 + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x-len/2 + !(Csts.camx), y+len + !(Csts.camy)); (x+len/2 + !(Csts.camx), y+len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 2; 3; 4; 7; 8; 9|] then
          draw_poly_line [|(x+len/2 + !(Csts.camx), y+len + !(Csts.camy)); (x+len/2 + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|2; 3; 4; 5; 6; 8; 9|] then
          draw_poly_line [|(x-len/2 + !(Csts.camx), y + !(Csts.camy)); (x+len/2 + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 3; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x+len/2 + !(Csts.camx), y-len + !(Csts.camy)); (x+len/2 + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 8; 9|] then
          draw_poly_line [|(x-len/2 + !(Csts.camx), y-len + !(Csts.camy)); (x+len/2 + !(Csts.camx), y-len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 6; 8|] then
          draw_poly_line [|(x-len/2 + !(Csts.camx), y-len + !(Csts.camy)); (x-len/2 + !(Csts.camx), y + !(Csts.camy))|];

      n := !n/10;
  done ;
  rv := x0 + offset + size*(len*11/7) ;;

let draw_integer_alignedleft ?retval:(rv=fodder) x0 y n0 len =
  (* 7-seg display 2 *)
  set_line_width (max 1 (len/4));
  let n = ref n0 in
  let size = Math.ln_b 10 n0 in

  let cur_x = ref (x0 + size*(len*11/7)) in

  if !n < 0 then begin
      n := !n * (-1);
      draw_poly_line [|(x0, y); (x0+len, y)|];
      cur_x := !cur_x + (len*11/7)
  end;

  for i = 0 to size do
      let x = !cur_x in
      if Array.mem (!n mod 10) [|0; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y+len + !(Csts.camy)); (x + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y+len + !(Csts.camy)); (x+len + !(Csts.camx), y+len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 2; 3; 4; 7; 8; 9|] then
          draw_poly_line [|(x+len + !(Csts.camx), y+len + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|2; 3; 4; 5; 6; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 3; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x+len + !(Csts.camx), y-len + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y-len + !(Csts.camy)); (x+len + !(Csts.camx), y-len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 6; 8|] then
          draw_poly_line [|(x + !(Csts.camx), y-len + !(Csts.camy)); (x + !(Csts.camx), y + !(Csts.camy))|];

      n := !n/10;
      cur_x := !cur_x - (len*11/7);
    done ;
    rv := (x0 + (size+1)*(len*11/7)) ;;

let draw_integer_alignedright ?retval:(rv=fodder) x0 y n0 len =
  (* 7-seg display 2 *)
  set_line_width (max 1 (len/4));
  let n = ref n0 in
  let size = Math.ln_b 10 n0 in

  let cur_x = ref (x0 - len*11/7) in

  if !n < 0 then begin
      n := !n * (-1);
      draw_poly_line [|(x0, y); (x0-(size+1)*len, y)|];
      cur_x := !cur_x + (len*11/7)
  end;

  for i = 0 to size do
      let x = !cur_x in
      if Array.mem (!n mod 10) [|0; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y+len + !(Csts.camy)); (x + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y+len + !(Csts.camy)); (x+len + !(Csts.camx), y+len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 2; 3; 4; 7; 8; 9|] then
          draw_poly_line [|(x+len + !(Csts.camx), y+len + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|2; 3; 4; 5; 6; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 1; 3; 4; 5; 6; 7; 8; 9|] then
          draw_poly_line [|(x+len + !(Csts.camx), y-len + !(Csts.camy)); (x+len + !(Csts.camx), y + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 3; 5; 6; 8; 9|] then
          draw_poly_line [|(x + !(Csts.camx), y-len + !(Csts.camy)); (x+len + !(Csts.camx), y-len + !(Csts.camy))|];

      if Array.mem (!n mod 10) [|0; 2; 6; 8|] then
          draw_poly_line [|(x + !(Csts.camx), y-len + !(Csts.camy)); (x + !(Csts.camx), y + !(Csts.camy))|];

      n := !n/10;
      cur_x := !cur_x - (len*11/7);
    done ;
    rv := (x0 + (len*11/7)) ;;

let decode_letter x y len arr =
  set_line_width 3;
  if arr.(0) = 1 then
      draw_poly_line [|(x, y+len); (x, y)|];
  if arr.(1) = 1 then
      draw_poly_line [|(x, y-len); (x, y)|];
  if arr.(2) = 1 then
      draw_poly_line [|(x, y+len); (x+len, y+len)|];
  if arr.(3) = 1 then
      draw_poly_line [|(x, y+len); (x+len, y)|];
  if arr.(4) = 1 then
     draw_poly_line [|(x, y); (x+len, y+len)|];
  if arr.(5) = 1 then
      draw_poly_line [|(x, y); (x+len, y)|];
  if arr.(6) = 1 then
      draw_poly_line [|(x, y); (x+len, y-len)|];
  if arr.(7) = 1 then
      draw_poly_line [|(x, y-len); (x+len, y)|];
  if arr.(8) = 1 then
      draw_poly_line [|(x+len, y-len); (x, y-len)|];
  if arr.(9) = 1 then
      draw_poly_line [|(x+len, y+len); (x+len, y)|];
  if arr.(10) = 1 then
        draw_poly_line [|(x+len, y-len); (x+len, y)|];;

let draw_letter x y c len = match c with
    |'a'|'A' -> decode_letter x y len [|1; 1; 1; 0; 0; 1; 0; 0; 0; 1; 1|]
    |'b'|'B' -> decode_letter x y len [|1; 1; 0; 0; 0; 1; 0; 0; 1; 0; 1|]
    |'c'|'C' -> decode_letter x y len [|1; 1; 1; 0; 0; 0; 0; 0; 1; 0; 0|]
    |'d'|'D' -> decode_letter x y len [|0; 0; 1; 0; 0; 0; 0; 0; 1; 1; 1|]; draw_poly_line [|(x+len/2, y+len); (x+len/2, y-len)|]
    |'e'|'E' -> decode_letter x y len [|1; 1; 1; 0; 0; 1; 0; 0; 1; 0; 0|]
    |'f'|'F' -> decode_letter x y len [|1; 1; 1; 0; 0; 1; 0; 0; 0; 0; 0|]
    |'g'|'G' -> decode_letter x y len [|1; 1; 1; 0; 0; 0; 0; 0; 1; 0; 1|]
    |'h'|'H' -> decode_letter x y len [|1; 1; 0; 0; 0; 1; 0; 0; 0; 1; 1|]
    |'i'|'I' -> draw_poly_line [|(x+len/2, y+len); (x+len/2, y-len)|];
    |'j'|'J' -> decode_letter x y len [|0; 1; 0; 0; 0; 0; 0; 0; 1; 1; 1|]
    |'k'|'K' -> decode_letter x y len [|1; 1; 0; 0; 1; 0; 1; 0; 0; 0; 0|]
    |'l'|'L' -> decode_letter x y len [|1; 1; 0; 0; 0; 0; 0; 0; 1; 0; 0|]
    |'m'|'M' -> decode_letter x y len [|1; 1; 0; 0; 0; 0; 0; 0; 0; 1; 1|]; draw_poly_line [|(x, y+len); (x+len/2, y)|]; draw_poly_line [|(x+len/2, y); (x+len, y+len)|]
    |'n'|'N' -> decode_letter x y len [|1; 1; 0; 1; 0; 0; 0; 0; 0; 1; 1|]
    |'o'|'O' -> decode_letter x y len [|1; 1; 1; 0; 0; 0; 0; 0; 1; 1; 1|]
    |'p'|'P' -> decode_letter x y len [|1; 1; 1; 0; 0; 1; 0; 0; 0; 1; 0|]
    |'q'|'Q' -> decode_letter x y len [|1; 0; 1; 0; 0; 1; 0; 0; 0; 1; 1|]
    |'r'|'R' -> decode_letter x y len [|1; 1; 1; 0; 0; 1; 1; 0; 0; 1; 0|]
    |'s'|'S' -> decode_letter x y len [|1; 0; 1; 0; 0; 1; 0; 0; 1; 0; 1|]
    |'t'|'T' -> decode_letter x y len [|1; 1; 0; 0; 0; 1; 0; 0; 1; 0; 0|]
    |'u'|'U' -> decode_letter x y len [|1; 1; 0; 0; 0; 0; 0; 0; 1; 1; 1|]
    |'v'|'V' -> decode_letter x y len [|1; 1; 0; 0; 0; 0; 0; 1; 0; 1; 0|]
    |'w'|'W' -> decode_letter x y len [|1; 1; 0; 0; 0; 0; 1; 1; 0; 1; 1|]
    |'x'|'X' -> draw_poly_line [|(x, y+len); (x+len, y-len)|]; draw_poly_line [|(x, y-len); (x+len, y+len)|]
    |'y'|'Y' -> decode_letter x y len [|1; 0; 0; 0; 0; 1; 0; 1; 0; 1; 0|]
    |'z'|'Z' -> decode_letter x y len [|0; 1; 1; 0; 1; 0; 0; 0; 1; 0; 0|] 
    | _ -> () ;;

let draw_string x0 y s len =
    let cur_x = ref x0 in
    for i = 0 to String.length s -1 do
        draw_letter !cur_x y s.[i] len;
        cur_x := !cur_x + (len*10/7)
    done;;

let draw_string_centered x0 y s len =
    let cur_x = ref (x0 - (len*10/7)*(int_of_float ((float_of_int (String.length s)) /. 2.))) in
    for i = 0 to String.length s -1 do
        draw_letter !cur_x y s.[i] len;
        cur_x := !cur_x + (len*10/7)
    done;;