|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* MLTk, Tcl/Tk interface of OCaml *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Francois Rouaix, Francois Pessaux, Jun Furuse and Pierre Weis *)
|
|
Packit |
bd2e5d |
(* projet Cristal, INRIA Rocquencourt *)
|
|
Packit |
bd2e5d |
(* Jacques Garrigue, Kyoto University RIMS *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(* Copyright 2002 Institut National de Recherche en Informatique et *)
|
|
Packit |
bd2e5d |
(* en Automatique and Kyoto University. All rights reserved. *)
|
|
Packit |
bd2e5d |
(* This file is distributed under the terms of the GNU Library *)
|
|
Packit |
bd2e5d |
(* General Public License, with the special exception on linking *)
|
|
Packit |
bd2e5d |
(* described in file LICENSE found in the OCaml source tree. *)
|
|
Packit |
bd2e5d |
(* *)
|
|
Packit |
bd2e5d |
(***********************************************************************)
|
|
Packit |
bd2e5d |
(* find font information *)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let debug = ref false
|
|
Packit |
bd2e5d |
let log s =
|
|
Packit |
bd2e5d |
if !debug then try prerr_endline s with _ -> ()
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
type ('s, 'i) xlfd = {
|
|
Packit |
bd2e5d |
(* some of them are currently not interesting for me *)
|
|
Packit |
bd2e5d |
mutable foundry: 's;
|
|
Packit |
bd2e5d |
mutable family: 's;
|
|
Packit |
bd2e5d |
mutable weight: 's;
|
|
Packit |
bd2e5d |
mutable slant: 's;
|
|
Packit |
bd2e5d |
mutable setWidth: 's;
|
|
Packit |
bd2e5d |
mutable addStyle: 's;
|
|
Packit |
bd2e5d |
mutable pixelSize: 'i;
|
|
Packit |
bd2e5d |
mutable pointSize: 'i;
|
|
Packit |
bd2e5d |
mutable resolutionX: 'i;
|
|
Packit |
bd2e5d |
mutable resolutionY: 'i;
|
|
Packit |
bd2e5d |
mutable spacing: 's;
|
|
Packit |
bd2e5d |
mutable averageWidth: 'i;
|
|
Packit |
bd2e5d |
mutable registry: 's;
|
|
Packit |
bd2e5d |
mutable encoding: 's
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let copy xlfd = {xlfd with foundry= xlfd.foundry}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let string_of_xlfd s i xlfd =
|
|
Packit |
bd2e5d |
let foundry= s xlfd.foundry
|
|
Packit |
bd2e5d |
and family= s xlfd.family
|
|
Packit |
bd2e5d |
and weight= s xlfd.weight
|
|
Packit |
bd2e5d |
and slant= s xlfd.slant
|
|
Packit |
bd2e5d |
and setWidth = s xlfd.setWidth
|
|
Packit |
bd2e5d |
and addStyle = s xlfd.addStyle
|
|
Packit |
bd2e5d |
and pixelSize= i xlfd.pixelSize
|
|
Packit |
bd2e5d |
and pointSize = i xlfd.pointSize
|
|
Packit |
bd2e5d |
and resolutionX = i xlfd.resolutionX
|
|
Packit |
bd2e5d |
and resolutionY = i xlfd.resolutionY
|
|
Packit |
bd2e5d |
and spacing= s xlfd.spacing
|
|
Packit |
bd2e5d |
and averageWidth = i xlfd.averageWidth
|
|
Packit |
bd2e5d |
and registry= s xlfd.registry
|
|
Packit |
bd2e5d |
and encoding = s xlfd.encoding in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
"-"^foundry^
|
|
Packit |
bd2e5d |
"-"^family^
|
|
Packit |
bd2e5d |
"-"^weight^
|
|
Packit |
bd2e5d |
"-"^slant^
|
|
Packit |
bd2e5d |
"-"^setWidth ^
|
|
Packit |
bd2e5d |
"-"^addStyle ^
|
|
Packit |
bd2e5d |
"-"^pixelSize^
|
|
Packit |
bd2e5d |
"-"^pointSize ^
|
|
Packit |
bd2e5d |
"-"^resolutionX ^
|
|
Packit |
bd2e5d |
"-"^resolutionY ^
|
|
Packit |
bd2e5d |
"-"^spacing^
|
|
Packit |
bd2e5d |
"-"^averageWidth ^
|
|
Packit |
bd2e5d |
"-"^registry^
|
|
Packit |
bd2e5d |
"-"^encoding
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
exception Parse_Xlfd_Failure of string
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let parse_xlfd xlfd_string =
|
|
Packit |
bd2e5d |
(* this must not be a pattern *)
|
|
Packit |
bd2e5d |
let split_str char_sep str =
|
|
Packit |
bd2e5d |
let len = String.length str in
|
|
Packit |
bd2e5d |
let rec split beg cur =
|
|
Packit |
bd2e5d |
if cur >= len then [String.sub str beg (len - beg)]
|
|
Packit |
bd2e5d |
else if char_sep (String.get str cur)
|
|
Packit |
bd2e5d |
then
|
|
Packit |
bd2e5d |
let nextw = succ cur in
|
|
Packit |
bd2e5d |
(String.sub str beg (cur - beg))
|
|
Packit |
bd2e5d |
::(split nextw nextw)
|
|
Packit |
bd2e5d |
else split beg (succ cur) in
|
|
Packit |
bd2e5d |
split 0 0
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
match split_str (function '-' -> true | _ -> false) xlfd_string with
|
|
Packit |
bd2e5d |
| [ _; foundry; family; weight; slant; setWidth; addStyle; pixelSize;
|
|
Packit |
bd2e5d |
pointSize; resolutionX; resolutionY; spacing; averageWidth;
|
|
Packit |
bd2e5d |
registry; encoding ] ->
|
|
Packit |
bd2e5d |
{ foundry= foundry;
|
|
Packit |
bd2e5d |
family= family;
|
|
Packit |
bd2e5d |
weight= weight;
|
|
Packit |
bd2e5d |
slant= slant;
|
|
Packit |
bd2e5d |
setWidth= setWidth;
|
|
Packit |
bd2e5d |
addStyle= addStyle;
|
|
Packit |
bd2e5d |
pixelSize= int_of_string pixelSize;
|
|
Packit |
bd2e5d |
pointSize= int_of_string pointSize;
|
|
Packit |
bd2e5d |
resolutionX= int_of_string resolutionX;
|
|
Packit |
bd2e5d |
resolutionY= int_of_string resolutionY;
|
|
Packit |
bd2e5d |
spacing= spacing;
|
|
Packit |
bd2e5d |
averageWidth= int_of_string averageWidth;
|
|
Packit |
bd2e5d |
registry= registry;
|
|
Packit |
bd2e5d |
encoding= encoding;
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
| _ -> raise (Parse_Xlfd_Failure xlfd_string)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
type valid_xlfd = (string, int) xlfd
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let string_of_valid_xlfd = string_of_xlfd (fun x -> x) string_of_int
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
type pattern = (string option, int option) xlfd
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let empty_pattern =
|
|
Packit |
bd2e5d |
{ foundry= None;
|
|
Packit |
bd2e5d |
family= None;
|
|
Packit |
bd2e5d |
weight= None;
|
|
Packit |
bd2e5d |
slant= None;
|
|
Packit |
bd2e5d |
setWidth= None;
|
|
Packit |
bd2e5d |
addStyle= None;
|
|
Packit |
bd2e5d |
pixelSize= None;
|
|
Packit |
bd2e5d |
pointSize= None;
|
|
Packit |
bd2e5d |
resolutionX= None;
|
|
Packit |
bd2e5d |
resolutionY= None;
|
|
Packit |
bd2e5d |
spacing= None;
|
|
Packit |
bd2e5d |
averageWidth= None;
|
|
Packit |
bd2e5d |
registry= None;
|
|
Packit |
bd2e5d |
encoding= None;
|
|
Packit |
bd2e5d |
}
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let string_of_pattern =
|
|
Packit |
bd2e5d |
let pat f = function
|
|
Packit |
bd2e5d |
Some x -> f x
|
|
Packit |
bd2e5d |
| None -> "*"
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let pat_string = pat (fun x -> x) in
|
|
Packit |
bd2e5d |
let pat_int = pat string_of_int in
|
|
Packit |
bd2e5d |
string_of_xlfd pat_string pat_int
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let is_vector_font xlfd =
|
|
Packit |
bd2e5d |
(xlfd.pixelSize = 0 && xlfd.resolutionX = 0 && xlfd.resolutionY = 0) ||
|
|
Packit |
bd2e5d |
xlfd.spacing <> "c"
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let list_fonts dispname pattern =
|
|
Packit |
bd2e5d |
let dispopt = match dispname with
|
|
Packit |
bd2e5d |
None -> ""
|
|
Packit |
bd2e5d |
| Some x -> "-display " ^ x
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let result = List.map parse_xlfd
|
|
Packit |
bd2e5d |
(Shell.subshell ("xlsfonts "^dispopt^" -fn "^string_of_pattern pattern))
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
if result = [] then raise Not_found
|
|
Packit |
bd2e5d |
else result
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let available_pixel_size_aux dispname pattern =
|
|
Packit |
bd2e5d |
(* return available pixel size without font resizing *)
|
|
Packit |
bd2e5d |
(* to obtain good result, *)
|
|
Packit |
bd2e5d |
(* the pattern should contain as many information as possible *)
|
|
Packit |
bd2e5d |
let pattern = copy pattern in
|
|
Packit |
bd2e5d |
pattern.pixelSize <- None;
|
|
Packit |
bd2e5d |
let xlfds = list_fonts dispname pattern in
|
|
Packit |
bd2e5d |
let pxszs = Hashtbl.create 107 in
|
|
Packit |
bd2e5d |
List.iter (fun xlfd ->
|
|
Packit |
bd2e5d |
Hashtbl.add pxszs xlfd.pixelSize xlfd) xlfds;
|
|
Packit |
bd2e5d |
pxszs
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let extract_size_font_hash tbl =
|
|
Packit |
bd2e5d |
let keys = ref [] in
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun k _ ->
|
|
Packit |
bd2e5d |
if not (List.mem k !keys) then keys := k :: !keys) tbl;
|
|
Packit |
bd2e5d |
List.sort (fun (k1,_) (k2,_) -> compare k1 k2)
|
|
Packit |
bd2e5d |
(List.map (fun k -> k, Hashtbl.find_all tbl k) !keys)
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let available_pixel_size dispname pattern =
|
|
Packit |
bd2e5d |
let pxszs = available_pixel_size_aux dispname pattern in
|
|
Packit |
bd2e5d |
extract_size_font_hash pxszs
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let nearest_pixel_size dispname vector_ok pattern =
|
|
Packit |
bd2e5d |
(* find the font with the nearest pixel size *)
|
|
Packit |
bd2e5d |
log ("\n*** "^string_of_pattern pattern);
|
|
Packit |
bd2e5d |
let pxlsz =
|
|
Packit |
bd2e5d |
match pattern.pixelSize with
|
|
Packit |
bd2e5d |
None -> raise (Failure "invalid pixelSize pattern")
|
|
Packit |
bd2e5d |
| Some x -> x
|
|
Packit |
bd2e5d |
in
|
|
Packit |
bd2e5d |
let tbl = available_pixel_size_aux dispname pattern in
|
|
Packit |
bd2e5d |
let newtbl = Hashtbl.create 107 in
|
|
Packit |
bd2e5d |
Hashtbl.iter (fun s xlfd ->
|
|
Packit |
bd2e5d |
if vector_ok then
|
|
Packit |
bd2e5d |
if s = 0 then begin
|
|
Packit |
bd2e5d |
if is_vector_font xlfd then begin
|
|
Packit |
bd2e5d |
log (Printf.sprintf "%s is vector" (string_of_valid_xlfd xlfd));
|
|
Packit |
bd2e5d |
xlfd.pixelSize <- pxlsz;
|
|
Packit |
bd2e5d |
Hashtbl.add newtbl pxlsz xlfd
|
|
Packit |
bd2e5d |
end
|
|
Packit |
bd2e5d |
end else Hashtbl.add newtbl s xlfd
|
|
Packit |
bd2e5d |
else if not (is_vector_font xlfd) && s <> 0 then
|
|
Packit |
bd2e5d |
Hashtbl.add newtbl s xlfd) tbl;
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let size_font_table = extract_size_font_hash newtbl in
|
|
Packit |
bd2e5d |
|
|
Packit |
bd2e5d |
let diff = ref 10000 in
|
|
Packit |
bd2e5d |
let min = ref None in
|
|
Packit |
bd2e5d |
List.iter (fun (s,xlfds) ->
|
|
Packit |
bd2e5d |
let d = abs(s - pxlsz) in
|
|
Packit |
bd2e5d |
if d < !diff then begin
|
|
Packit |
bd2e5d |
min := Some (s,xlfds);
|
|
Packit |
bd2e5d |
diff := d
|
|
Packit |
bd2e5d |
end) size_font_table;
|
|
Packit |
bd2e5d |
(* if it contains more than one font, just return the first *)
|
|
Packit |
bd2e5d |
match !min with
|
|
Packit |
bd2e5d |
| None -> raise Not_found
|
|
Packit |
bd2e5d |
| Some(s, xlfds) ->
|
|
Packit |
bd2e5d |
log (Printf.sprintf "Size %d is selected" s);
|
|
Packit |
bd2e5d |
List.iter (fun xlfd -> log (string_of_valid_xlfd xlfd)) xlfds;
|
|
Packit |
bd2e5d |
List.hd xlfds
|