| 320 | } |
| 321 | |
| 322 | void TryLoad(const wchar_t* query, const FontQueryResponse& response) |
| 323 | { |
| 324 | struct EnumInfo |
| 325 | { |
| 326 | const FontQueryResponse* response; |
| 327 | std::vector<char> maskedFace; |
| 328 | }; |
| 329 | |
| 330 | wil::unique_hdc_window hDC = wil::GetWindowDC(HWND_DESKTOP); |
| 331 | LOGFONTW lf{}; |
| 332 | wcscpy_s(lf.lfFaceName, LF_FACESIZE, query); |
| 333 | |
| 334 | EnumInfo enumInfo; |
| 335 | enumInfo.response = &response; |
| 336 | enumInfo.maskedFace.assign(response.fonts_size(), 0); |
| 337 | |
| 338 | Detour::Original::EnumFontFamiliesExW( |
| 339 | hDC.get(), &lf, [](const LOGFONT* lpelfe, const TEXTMETRIC* lpntme, DWORD dwFontType, LPARAM lParam)-> int |
| 340 | { |
| 341 | EnumInfo& info = *reinterpret_cast<EnumInfo*>(lParam); |
| 342 | auto faceName = WideToUtf8String(lpelfe->lfFaceName); |
| 343 | for (int i = 0; i < info.response->fonts_size(); ++i) |
| 344 | { |
| 345 | if (info.maskedFace[i])continue; |
| 346 | auto& face = info.response->fonts()[i]; |
| 347 | if ((std::ranges::find(face.familyname(), faceName) != face.familyname().end() |
| 348 | || face.ispsoutline() |
| 349 | && std::ranges::find(face.postscriptname(), faceName) != face.postscriptname().end() |
| 350 | || std::ranges::find(face.gdifullname(), faceName) != face. |
| 351 | gdifullname().end()) |
| 352 | && (!!face.oblique() == !!lpelfe->lfItalic && face.weight() == lpelfe->lfWeight) |
| 353 | ) |
| 354 | { |
| 355 | info.maskedFace[i] = 1; |
| 356 | } |
| 357 | } |
| 358 | return TRUE; |
| 359 | }, reinterpret_cast<LPARAM>(&enumInfo), 0); |
| 360 | |
| 361 | FontLoadFeedback feedback; |
| 362 | |
| 363 | for (int i = 0; i < response.fonts_size(); ++i) |
| 364 | { |
| 365 | if (enumInfo.maskedFace[i])continue; |
| 366 | auto path = Utf8ToWideString(response.fonts()[i].path()); |
| 367 | feedback.add_path(response.fonts()[i].path()); |
| 368 | |
| 369 | AddFontResourceExW(path.c_str(), FR_PRIVATE, nullptr); |
| 370 | |
| 371 | EventLog::GetInstance().LogDllLoadFont(GetCurrentProcessId(), GetCurrentThreadId(), path.c_str()); |
| 372 | } |
| 373 | |
| 374 | SendFeedbackAsync(std::move(feedback)); |
| 375 | } |
| 376 | |
| 377 | void QueryAndLoad(const wchar_t* query) |
| 378 | { |
no test coverage detected