color.ml 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. open Types
  2. let hex6 = Str.regexp "\\([0-9a-f]\\)\\1\\([0-9a-f]\\)\\2\\([0-9a-f]\\)\\3"
  3. let is_num = function
  4. | Number (n, (None | Some "%")) -> true
  5. | _ -> false
  6. let clip = function
  7. | Number (n, (None | Some "%")) when n < 0. -> Number (0., Some "%")
  8. | Number (n, None) when n > 255. -> Number (255., None)
  9. | Number (n, Some "%") when n > 100. -> Number (100., Some "%")
  10. | value -> value
  11. let rec short = function
  12. | Ident "aqua" -> Hexcolor "0ff"
  13. | Ident "black" -> Hexcolor "000"
  14. | Ident "blue" -> Hexcolor "00f"
  15. | Ident "fuchsia" -> Hexcolor "f0f"
  16. | Ident "lime" -> Hexcolor "0f0"
  17. | Ident "white" -> Hexcolor "fff"
  18. | Ident "yellow" -> Hexcolor "ff0"
  19. | Hexcolor "808080" -> Ident "gray"
  20. | Hexcolor "008000" -> Ident "green"
  21. | Hexcolor "800000" -> Ident "maroon"
  22. | Hexcolor "000080" -> Ident "navy"
  23. | Hexcolor "8080000"-> Ident "olive"
  24. | Hexcolor "800080" -> Ident "purple"
  25. | Hexcolor "ff0000"
  26. | Hexcolor "f00" -> Ident "red"
  27. | Hexcolor "c0c0c0" -> Ident "silver"
  28. | Hexcolor "008080" -> Ident "teal"
  29. (* #aabbcc -> #abc *)
  30. | Hexcolor h when Str.string_match hex6 h 0 ->
  31. let gr n = Str.matched_group n h in
  32. Hexcolor (gr 1 ^ gr 2 ^ gr 3)
  33. (* rgb(r,g,b) -> #rrggbb *)
  34. | Function ("rgb", Nary (",", [r; g; b]))
  35. when is_num r & is_num g & is_num b ->
  36. let i c =
  37. match clip c with
  38. | Number (n, None) -> int_of_float n
  39. | Number (n, Some "%") -> int_of_float (n *. 2.55 +. 0.5)
  40. | _ -> assert false
  41. in
  42. short (Hexcolor (Printf.sprintf "%02x%02x%02x" (i r) (i g) (i b)))
  43. (* clip rgb values, e.g. rgb(-1,256,0) -> rgb(0,255,0) *)
  44. | Function ("rgb", Nary (",", [r; g; b])) ->
  45. Function ("rgb", Nary (",", [clip r; clip g; clip b]))
  46. | c -> c
  47. let rec compress_props = function
  48. | [] -> []
  49. | ("color", c, i) :: tl ->
  50. ("color", short c, i) :: compress_props tl
  51. | hd :: tl -> hd :: compress_props tl
  52. let rec compress = function
  53. | [] -> []
  54. | Ruleset (selectors, properties) :: tl ->
  55. Ruleset (selectors, compress_props properties) :: compress tl
  56. | hd :: tl ->
  57. hd :: compress tl