blob: 26df71051068e42ac1402636697ff3a226d80ca0 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/services/font_data/font_data_service_impl.h"
#include <memory>
#include <utility>
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/test/task_environment.h"
#include "components/services/font_data/public/mojom/font_data_service.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "skia/ext/font_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace font_data_service {
namespace {
class TestFontDataService : public FontDataServiceImpl {
public:
TestFontDataService() = default;
~TestFontDataService() override = default;
TestFontDataService(const TestFontDataService&) = delete;
TestFontDataService& operator=(const TestFontDataService&) = delete;
base::File GetFileHandle(SkTypeface& typeface) override {
if (use_memory_fallback_) {
// Return an empty file handle to simulate the fallback.
return base::File();
}
return FontDataServiceImpl::GetFileHandle(typeface);
}
void set_use_memory_fallback(bool fallback) {
use_memory_fallback_ = fallback;
}
private:
bool use_memory_fallback_ = false;
};
class FontDataServiceImplUnitTest : public testing::Test {
protected:
FontDataServiceImplUnitTest()
: receiver_(&impl_, font_service_.BindNewPipeAndPassReceiver()) {}
~FontDataServiceImplUnitTest() override = default;
base::test::SingleThreadTaskEnvironment environment_;
mojo::Remote<mojom::FontDataService> font_service_;
TestFontDataService impl_;
mojo::Receiver<mojom::FontDataService> receiver_;
};
mojom::TypefaceStylePtr CreateTypefaceStyle(int weight,
int width,
mojom::TypefaceSlant slant) {
mojom::TypefaceStylePtr style(mojom::TypefaceStyle::New());
style->weight = weight;
style->width = width;
style->slant = slant;
return style;
}
TEST_F(FontDataServiceImplUnitTest, MatchFamilyName) {
mojom::MatchFamilyNameResultPtr out_result;
std::string family_name = "Segoe UI";
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
font_service_->MatchFamilyName(
family_name, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
&out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
EXPECT_TRUE(out_result->typeface_data->is_font_file());
EXPECT_TRUE(out_result->typeface_data->get_font_file().IsValid());
}
TEST_F(FontDataServiceImplUnitTest, MatchFamilyNameMemoryCacheSize) {
mojom::MatchFamilyNameResultPtr out_result;
std::string family_name = "Segoe UI";
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
impl_.set_use_memory_fallback(true);
// There should be one entry added to the cache.
font_service_->MatchFamilyName(
family_name, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
&out_result);
EXPECT_TRUE(out_result->typeface_data->is_region());
EXPECT_TRUE(out_result->typeface_data->get_region().IsValid());
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 1u);
// Call with the same family name and style. Cache should stay the same
font_service_->MatchFamilyName(
family_name, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
&out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 1u);
// Call with a different family name. Cache should increase.
// Bahnschrift is a font with 2 variations. Check result for 2 coordinates.
font_service_->MatchFamilyName(
"Bahnschrift", CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
&out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 2u);
EXPECT_EQ(out_result->variation_position->coordinateCount, 2u);
EXPECT_EQ(out_result->variation_position->coordinates.size(), 2u);
// Call with a different font style. Cache should increase.
font_service_->MatchFamilyName(
family_name, CreateTypefaceStyle(600, 5, mojom::TypefaceSlant::kOblique),
&out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 3u);
// Call with a gibberish family name. Cache should be the same. Result should
// be nullptr.
font_service_->MatchFamilyName(
"not a real font",
CreateTypefaceStyle(600, 5, mojom::TypefaceSlant::kOblique), &out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 3u);
EXPECT_EQ(out_result.get(), nullptr);
}
TEST_F(FontDataServiceImplUnitTest, MatchFamilyNameCharacterNoLanguageTags) {
mojom::MatchFamilyNameResultPtr out_result;
std::string family_name = "Segoe UI";
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
SkUnichar uni_char = 0x0041; // 'A'
font_service_->MatchFamilyNameCharacter(
family_name, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
{}, uni_char, &out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
EXPECT_TRUE(out_result->typeface_data->is_font_file());
EXPECT_TRUE(out_result->typeface_data->get_font_file().IsValid());
}
TEST_F(FontDataServiceImplUnitTest, MatchFamilyNameCharacterWithLanguageTags) {
mojom::MatchFamilyNameResultPtr out_result;
std::string family_name = "Segoe UI";
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
SkUnichar uni_char = 0x0041; // 'A'
font_service_->MatchFamilyNameCharacter(
family_name, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
{"zh"}, uni_char, &out_result);
EXPECT_EQ(impl_.GetCacheSizeForTesting(), 0u);
EXPECT_TRUE(out_result->typeface_data->is_font_file());
EXPECT_TRUE(out_result->typeface_data->get_font_file().IsValid());
}
TEST_F(FontDataServiceImplUnitTest, GetAllFamilyNames) {
std::vector<std::string> out_result;
font_service_->GetAllFamilyNames(&out_result);
// This tests that GetAllFamilyNames returns the actual font family names
// installed on the system. There's no guarantee that these are going to be
// stable across systems, so just assert that the function is returning
// something, and that the names are non-empty.
EXPECT_GT(out_result.size(), 0UL);
for (const auto& family_name : out_result) {
EXPECT_GT(family_name.size(), 0UL);
}
}
TEST_F(FontDataServiceImplUnitTest, LegacyMakeTypefaceNullFamilyName) {
mojom::MatchFamilyNameResultPtr out_result;
// LegacyMakeTypeface should return the default font if `family_name` is null.
font_service_->LegacyMakeTypeface(
std::nullopt, CreateTypefaceStyle(400, 5, mojom::TypefaceSlant::kRoman),
&out_result);
EXPECT_TRUE(out_result->typeface_data->is_font_file());
EXPECT_TRUE(out_result->typeface_data->get_font_file().IsValid());
}
} // namespace
} // namespace font_data_service