Basic FreeType renderer implementation.
[gdipp.git] / gdipp_server / font_link.cpp
blob9a914ccd24bfb621ceca0db2c5bc6529f57d497a
1 #include "stdafx.h"
2 #include "font_link.h"
4 namespace gdipp
7 #define MAX_VALUE_NAME 1024
9 font_link::font_link()
11 // read font linking information from registry, and store in std::map
13 LONG l_ret;
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";
18 HKEY key_ft;
19 l_ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, Fonts, 0, KEY_QUERY_VALUE, &key_ft);
20 if (l_ret != ERROR_SUCCESS)
21 return;
23 HKEY key_fl;
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);
28 return;
31 DWORD value_count;
32 DWORD max_data_len;
33 wchar_t value_name[MAX_VALUE_NAME];
34 BYTE *value_data;
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);
44 // no font installed
45 if (value_count == 0)
46 return;
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
73 if (value_count == 0)
74 return;
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)
110 *next_comma = L'\0';
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;
128 scaling_prop = 0;
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];
140 scaling_prop = 1;
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];
152 ss >> factor1;
154 ss.clear();
155 ss.str(L"");
157 ss << properties[scaling_prop + 1];
158 ss >> factor2;
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())
182 return NULL;
183 else
185 if (index < iter->second.size())
186 return &iter->second[index];
187 else
188 return NULL;
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())
197 return 0;
198 else
199 return iter->second.size();