7 #define MAX_VALUE_NAME 1024
11 // read font linking information from registry, and store in std::map
15 const wchar_t *Fonts
= L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
16 const wchar_t *FontLink
= L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink";
19 l_ret
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Fonts
, 0, KEY_QUERY_VALUE
, &key_ft
);
20 if (l_ret
!= ERROR_SUCCESS
)
24 l_ret
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, FontLink
, 0, KEY_QUERY_VALUE
, &key_fl
);
25 if (l_ret
!= ERROR_SUCCESS
)
27 l_ret
= RegCloseKey(key_ft
);
33 wchar_t value_name
[MAX_VALUE_NAME
];
36 // font file name -> font face name mapping
37 std::map
<std::wstring
, std::wstring
, wstring_ci_less
> fonts_table
;
39 // get font_file_name -> font_face mapping from the "Fonts" registry key
41 l_ret
= RegQueryInfoKeyW(key_ft
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &value_count
, NULL
, &max_data_len
, NULL
, NULL
);
42 assert(l_ret
== ERROR_SUCCESS
);
48 // max_data_len is in BYTE
49 value_data
= static_cast<BYTE
*>(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS
, max_data_len
));
50 assert(value_data
!= NULL
);
52 for (DWORD i
= 0; i
< value_count
; ++i
)
54 DWORD name_len
= MAX_VALUE_NAME
;
55 DWORD data_len
= max_data_len
;
57 l_ret
= RegEnumValueW(key_ft
, i
, value_name
, &name_len
, NULL
, NULL
, value_data
, &data_len
);
58 assert(l_ret
== ERROR_SUCCESS
);
60 std::wstring curr_face
= value_name
;
61 std::wstring font_file
= reinterpret_cast<wchar_t *>(value_data
);
62 curr_face
= curr_face
.substr(0, curr_face
.find('(') - 1);
63 fonts_table
[font_file
] = curr_face
;
66 // get font_face -> font_file_name mapping from the "SystemLink" registry key
67 // complete the font linking by composing the two mappings
69 l_ret
= RegQueryInfoKey(key_fl
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &value_count
, NULL
, &max_data_len
, NULL
, NULL
);
70 assert(l_ret
== ERROR_SUCCESS
);
72 // no font link information
76 value_data
= static_cast<BYTE
*>(HeapReAlloc(GetProcessHeap(), 0, value_data
, max_data_len
));
77 assert(value_data
!= NULL
);
79 for (DWORD i
= 0; i
< value_count
; ++i
)
81 DWORD name_len
= MAX_VALUE_NAME
;
82 DWORD data_len
= max_data_len
;
84 l_ret
= RegEnumValueW(key_fl
, i
, value_name
, &name_len
, NULL
, NULL
, value_data
, &data_len
);
85 assert(l_ret
== ERROR_SUCCESS
);
87 _link_table
[value_name
] = std::vector
<font_link_node
>();
88 size_t line_start
= 0;
90 std::set
<std::wstring
, wstring_ci_less
> curr_font_family_pool
;
92 while (line_start
< data_len
- sizeof(wchar_t))
94 font_link_node new_link
;
95 new_link
.scaling
= 1.0;
97 wchar_t *curr_font
= reinterpret_cast<wchar_t *>(value_data
+ line_start
);
99 // including the trailing '\0'
100 line_start
+= (wcslen(curr_font
) + 1) * sizeof(wchar_t);
102 std::vector
<wchar_t *> properties
;
103 wchar_t *curr_comma
= curr_font
- 1;
104 while (curr_comma
!= NULL
)
106 wchar_t *next_comma
= wcschr(curr_comma
+ 1, L
',');
108 if (next_comma
!= NULL
)
111 properties
.push_back(next_comma
+ 1);
114 curr_comma
= next_comma
;
117 // font family starts with alphabetic character
119 size_t scaling_prop
= properties
.size();
120 if (properties
.empty() || !isalpha(*properties
[0]))
122 // this is not a ttc file
123 // lookup the Fonts table
124 std::map
<std::wstring
, std::wstring
, wstring_ci_less
>::const_iterator iter
= fonts_table
.find(curr_font
);
125 if (iter
!= fonts_table
.end())
126 new_link
.font_family
= iter
->second
;
130 else if (isalpha(*properties
[0]))
132 // this is a ttc file
133 // use the specified font face
134 if (fonts_table
.find(curr_font
) != fonts_table
.end())
136 // trust the face name
137 new_link
.font_family
= properties
[0];
143 if (scaling_prop
+ 2 == properties
.size())
145 // scaling factors are provided
146 // use only if both two factors are specified
148 int factor1
, factor2
;
149 std::wstringstream ss
;
151 ss
<< properties
[scaling_prop
];
157 ss
<< properties
[scaling_prop
+ 1];
160 new_link
.scaling
= (factor1
/ 128.0) * (96.0 / factor2
);
163 if (!new_link
.font_family
.empty() && curr_font_family_pool
.find(new_link
.font_family
) == curr_font_family_pool
.end())
165 _link_table
[value_name
].push_back(new_link
);
166 curr_font_family_pool
.insert(new_link
.font_family
);
171 HeapFree(GetProcessHeap(), 0, value_data
);
173 l_ret
= RegCloseKey(key_ft
);
174 l_ret
= RegCloseKey(key_fl
);
177 const font_link_node
*font_link::lookup_link(const wchar_t *font_name
, size_t index
) const
179 const link_map::const_iterator iter
= _link_table
.find(font_name
);
181 if (iter
== _link_table
.end())
185 if (index
< iter
->second
.size())
186 return &iter
->second
[index
];
192 size_t font_link::get_link_count(const wchar_t *font_name
) const
194 const link_map::const_iterator iter
= _link_table
.find(font_name
);
196 if (iter
== _link_table
.end())
199 return iter
->second
.size();