| // 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()); } |
| |
| bool EnumFontList(CFX_FontMapper* pMapper) override { |
| return 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() { |
| if (!PathService::GetExecutableDir(&font_path_)) |
| 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()); |
| } |