| // Copyright 2021 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "testing/test_fonts.h" | |
| #include <memory> | |
| #include <set> | |
| #include <utility> | |
| #include "core/fxge/cfx_fontmapper.h" | |
| #include "core/fxge/cfx_fontmgr.h" | |
| #include "core/fxge/cfx_gemodule.h" | |
| #include "core/fxge/systemfontinfo_iface.h" | |
| #include "testing/utils/path_service.h" | |
| namespace { | |
| ByteString RenameFontForTesting(const ByteString& face) { | |
| ByteString result; | |
| if (face.Contains("Arial") || face.Contains("Calibri") || | |
| face.Contains("Helvetica")) { | |
| // Sans | |
| result = "Arimo"; | |
| } else if (face.IsEmpty() || face.Contains("Times")) { | |
| // Serif | |
| result = "Tinos"; | |
| } else if (face.Contains("Courier")) { | |
| // Mono | |
| result = "Cousine"; | |
| } else { | |
| // Some tests expect the fallback font. | |
| return face; | |
| } | |
| if (face.Contains("Bold")) { | |
| result += " Bold"; | |
| } | |
| if (face.Contains("Italic") || face.Contains("Oblique")) { | |
| result += " Italic"; | |
| } | |
| return result; | |
| } | |
| // Intercepts font requests and renames font faces to those in test_fonts. | |
| class SystemFontInfoWrapper : public SystemFontInfoIface { | |
| public: | |
| explicit SystemFontInfoWrapper(std::unique_ptr<SystemFontInfoIface> impl) | |
| : impl_(std::move(impl)) {} | |
| ~SystemFontInfoWrapper() override { CHECK(active_fonts_.empty()); } | |
| void EnumFontList(CFX_FontMapper* pMapper) override { | |
| impl_->EnumFontList(pMapper); | |
| } | |
| void* MapFont(int weight, | |
| bool bItalic, | |
| FX_Charset charset, | |
| int pitch_family, | |
| const ByteString& face) override { | |
| void* font = impl_->MapFont(weight, bItalic, charset, pitch_family, | |
| RenameFontForTesting(face)); | |
| if (font) { | |
| bool inserted = active_fonts_.insert(font).second; | |
| CHECK(inserted); | |
| } | |
| return font; | |
| } | |
| void* GetFont(const ByteString& face) override { | |
| return impl_->GetFont(RenameFontForTesting(face)); | |
| } | |
| size_t GetFontData(void* hFont, | |
| uint32_t table, | |
| pdfium::span<uint8_t> buffer) override { | |
| return impl_->GetFontData(hFont, table, buffer); | |
| } | |
| bool GetFaceName(void* hFont, ByteString* name) override { | |
| auto face = RenameFontForTesting(*name); | |
| return impl_->GetFaceName(hFont, &face); | |
| } | |
| bool GetFontCharset(void* hFont, FX_Charset* charset) override { | |
| return impl_->GetFontCharset(hFont, charset); | |
| } | |
| void DeleteFont(void* hFont) override { | |
| CHECK(active_fonts_.erase(hFont)); | |
| impl_->DeleteFont(hFont); | |
| } | |
| private: | |
| std::unique_ptr<SystemFontInfoIface> impl_; | |
| std::set<void*> active_fonts_; | |
| }; | |
| } // namespace | |
| TestFonts::TestFonts() { | |
| font_path_ = PathService::GetExecutableDir(); | |
| if (font_path_.empty()) { | |
| return; | |
| } | |
| font_path_.push_back(PATH_SEPARATOR); | |
| font_path_.append("test_fonts"); | |
| font_paths_ = std::vector<const char*>{font_path_.c_str(), nullptr}; | |
| } | |
| TestFonts::~TestFonts() = default; | |
| void TestFonts::InstallFontMapper() { | |
| auto* font_mapper = CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper(); | |
| font_mapper->SetSystemFontInfo(std::make_unique<SystemFontInfoWrapper>( | |
| font_mapper->TakeSystemFontInfo())); | |
| } | |
| // static | |
| std::string TestFonts::RenameFont(const char* face) { | |
| ByteString renamed_face = RenameFontForTesting(face); | |
| return std::string(renamed_face.c_str()); | |
| } |