blob: 770e23e5ae3a9d3891dfec1b475a9222ebd96f3f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gfx/font_list.h"
#include <algorithm>
#include <string>
#include <vector>
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/font_names_testing.h"
namespace gfx {
namespace {
// Helper function for comparing fonts for equality.
std::string FontToString(const Font& font) {
std::string font_string = font.GetFontName();
font_string += "|";
font_string += base::IntToString(font.GetFontSize());
int style = font.GetStyle();
if (style & Font::ITALIC)
font_string += "|italic";
if (style & Font::UNDERLINE)
font_string += "|underline";
auto weight = font.GetWeight();
if (weight == Font::Weight::BLACK)
font_string += "|black";
else if (weight == Font::Weight::BOLD)
font_string += "|bold";
else if (weight == Font::Weight::EXTRA_BOLD)
font_string += "|extrabold";
else if (weight == Font::Weight::EXTRA_LIGHT)
font_string += "|extralight";
else if (weight == Font::Weight::LIGHT)
font_string += "|light";
else if (weight == Font::Weight::MEDIUM)
font_string += "|medium";
else if (weight == Font::Weight::NORMAL)
font_string += "|normal";
else if (weight == Font::Weight::SEMIBOLD)
font_string += "|semibold";
else if (weight == Font::Weight::THIN)
font_string += "|thin";
return font_string;
}
} // namespace
TEST(FontListTest, ParseDescription) {
std::vector<std::string> families;
int style = Font::NORMAL;
int size_pixels = 0;
Font::Weight weight = Font::Weight::NORMAL;
// Parse a well-formed description containing styles and a size.
EXPECT_TRUE(FontList::ParseDescription("Arial,Helvetica,Bold Italic 12px",
&families, &style, &size_pixels,
&weight));
ASSERT_EQ(2U, families.size());
EXPECT_EQ("Arial", families[0]);
EXPECT_EQ("Helvetica", families[1]);
EXPECT_EQ(Font::ITALIC, style);
EXPECT_EQ(Font::Weight::BOLD, weight);
EXPECT_EQ(12, size_pixels);
// Whitespace should be removed.
EXPECT_TRUE(FontList::ParseDescription(" Verdana , Italic Bold 10px ",
&families, &style, &size_pixels,
&weight));
ASSERT_EQ(1U, families.size());
EXPECT_EQ("Verdana", families[0]);
EXPECT_EQ(Font::ITALIC, style);
EXPECT_EQ(Font::Weight::BOLD, weight);
EXPECT_EQ(10, size_pixels);
// Invalid descriptions should be rejected.
EXPECT_FALSE(
FontList::ParseDescription("", &families, &style, &size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial,12", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial 12px", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial,12px,", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial,0px", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial,-1px", &families, &style,
&size_pixels, &weight));
EXPECT_FALSE(FontList::ParseDescription("Arial,foo 12px", &families, &style,
&size_pixels, &weight));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromDescString DISABLED_Fonts_FromDescString
#else
#define MAYBE_Fonts_FromDescString Fonts_FromDescString
#endif
TEST(FontListTest, MAYBE_Fonts_FromDescString) {
// Test init from font name size string.
FontList font_list = FontList("arial, Courier New, 13px");
const std::vector<Font>& fonts = font_list.GetFonts();
ASSERT_EQ(2U, fonts.size());
EXPECT_EQ("arial|13|normal", FontToString(fonts[0]));
EXPECT_EQ("Courier New|13|normal", FontToString(fonts[1]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromDescStringInFlexibleFormat \
DISABLED_Fonts_FromDescStringInFlexibleFormat
#else
#define MAYBE_Fonts_FromDescStringInFlexibleFormat \
Fonts_FromDescStringInFlexibleFormat
#endif
TEST(FontListTest, MAYBE_Fonts_FromDescStringInFlexibleFormat) {
// Test init from font name size string with flexible format.
FontList font_list = FontList(" arial , Courier New , 13px");
const std::vector<Font>& fonts = font_list.GetFonts();
ASSERT_EQ(2U, fonts.size());
EXPECT_EQ("arial|13|normal", FontToString(fonts[0]));
EXPECT_EQ("Courier New|13|normal", FontToString(fonts[1]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromDescStringWithStyleInFlexibleFormat \
DISABLED_Fonts_FromDescStringWithStyleInFlexibleFormat
#else
#define MAYBE_Fonts_FromDescStringWithStyleInFlexibleFormat \
Fonts_FromDescStringWithStyleInFlexibleFormat
#endif
TEST(FontListTest, MAYBE_Fonts_FromDescStringWithStyleInFlexibleFormat) {
// Test init from font name style size string with flexible format.
FontList font_list = FontList(
" arial , Courier New , Bold "
" Italic 13px");
const std::vector<Font>& fonts = font_list.GetFonts();
ASSERT_EQ(2U, fonts.size());
EXPECT_EQ("arial|13|italic|bold", FontToString(fonts[0]));
EXPECT_EQ("Courier New|13|italic|bold", FontToString(fonts[1]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromFont DISABLED_Fonts_FromFont
#else
#define MAYBE_Fonts_FromFont Fonts_FromFont
#endif
TEST(FontListTest, MAYBE_Fonts_FromFont) {
// Test init from Font.
Font font("Arial", 8);
FontList font_list = FontList(font);
const std::vector<Font>& fonts = font_list.GetFonts();
ASSERT_EQ(1U, fonts.size());
EXPECT_EQ("Arial|8|normal", FontToString(fonts[0]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromFontWithNonNormalStyle \
DISABLED_Fonts_FromFontWithNonNormalStyle
#else
#define MAYBE_Fonts_FromFontWithNonNormalStyle Fonts_FromFontWithNonNormalStyle
#endif
TEST(FontListTest, MAYBE_Fonts_FromFontWithNonNormalStyle) {
// Test init from Font with non-normal style.
Font font("Arial", 8);
FontList font_list(font.Derive(2, Font::NORMAL, Font::Weight::BOLD));
std::vector<Font> fonts = font_list.GetFonts();
ASSERT_EQ(1U, fonts.size());
EXPECT_EQ("Arial|10|bold", FontToString(fonts[0]));
font_list = FontList(font.Derive(-2, Font::ITALIC, Font::Weight::NORMAL));
fonts = font_list.GetFonts();
ASSERT_EQ(1U, fonts.size());
EXPECT_EQ("Arial|6|italic|normal", FontToString(fonts[0]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_FromFontVector DISABLED_Fonts_FromFontVector
#else
#define MAYBE_Fonts_FromFontVector Fonts_FromFontVector
#endif
TEST(FontListTest, MAYBE_Fonts_FromFontVector) {
// Test init from Font vector.
Font font("Arial", 8);
Font font_1("Courier New", 10);
std::vector<Font> input_fonts;
input_fonts.push_back(font.Derive(0, Font::NORMAL, Font::Weight::BOLD));
input_fonts.push_back(font_1.Derive(-2, Font::NORMAL, Font::Weight::BOLD));
FontList font_list = FontList(input_fonts);
const std::vector<Font>& fonts = font_list.GetFonts();
ASSERT_EQ(2U, fonts.size());
EXPECT_EQ("Arial|8|bold", FontToString(fonts[0]));
EXPECT_EQ("Courier New|8|bold", FontToString(fonts[1]));
}
TEST(FontListTest, FontDescString_GetStyle) {
FontList font_list = FontList("Arial,Sans serif, 8px");
EXPECT_EQ(Font::NORMAL, font_list.GetFontStyle());
EXPECT_EQ(Font::Weight::NORMAL, font_list.GetFontWeight());
font_list = FontList("Arial,Sans serif,Bold 8px");
EXPECT_EQ(Font::NORMAL, font_list.GetFontStyle());
EXPECT_EQ(Font::Weight::BOLD, font_list.GetFontWeight());
font_list = FontList("Arial,Sans serif,Italic 8px");
EXPECT_EQ(Font::ITALIC, font_list.GetFontStyle());
EXPECT_EQ(Font::Weight::NORMAL, font_list.GetFontWeight());
font_list = FontList("Arial,Italic Bold 8px");
EXPECT_EQ(Font::ITALIC, font_list.GetFontStyle());
EXPECT_EQ(Font::Weight::BOLD, font_list.GetFontWeight());
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_GetStyle DISABLED_Fonts_GetStyle
#else
#define MAYBE_Fonts_GetStyle Fonts_GetStyle
#endif
TEST(FontListTest, MAYBE_Fonts_GetStyle) {
std::vector<Font> fonts;
fonts.push_back(Font("Arial", 8));
fonts.push_back(Font("Sans serif", 8));
FontList font_list = FontList(fonts);
EXPECT_EQ(Font::NORMAL, font_list.GetFontStyle());
fonts[0] = fonts[0].Derive(0, Font::ITALIC, Font::Weight::BOLD);
fonts[1] = fonts[1].Derive(0, Font::ITALIC, Font::Weight::BOLD);
font_list = FontList(fonts);
EXPECT_EQ(Font::ITALIC, font_list.GetFontStyle());
EXPECT_EQ(Font::Weight::BOLD, font_list.GetFontWeight());
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_Derive DISABLED_Fonts_Derive
#else
#define MAYBE_Fonts_Derive Fonts_Derive
#endif
TEST(FontListTest, MAYBE_Fonts_Derive) {
std::vector<Font> fonts;
fonts.push_back(Font("Arial", 8));
fonts.push_back(Font("Courier New", 8));
FontList font_list = FontList(fonts);
FontList derived = font_list.Derive(5, Font::ITALIC, Font::Weight::BOLD);
const std::vector<Font>& derived_fonts = derived.GetFonts();
EXPECT_EQ(2U, derived_fonts.size());
EXPECT_EQ("Arial|13|italic|bold", FontToString(derived_fonts[0]));
EXPECT_EQ("Courier New|13|italic|bold", FontToString(derived_fonts[1]));
derived = font_list.Derive(5, Font::UNDERLINE, Font::Weight::BOLD);
const std::vector<Font>& underline_fonts = derived.GetFonts();
EXPECT_EQ(2U, underline_fonts.size());
EXPECT_EQ("Arial|13|underline|bold", FontToString(underline_fonts[0]));
EXPECT_EQ("Courier New|13|underline|bold", FontToString(underline_fonts[1]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_DeriveWithSizeDelta DISABLED_Fonts_DeriveWithSizeDelta
#else
#define MAYBE_Fonts_DeriveWithSizeDelta Fonts_DeriveWithSizeDelta
#endif
TEST(FontListTest, MAYBE_Fonts_DeriveWithSizeDelta) {
std::vector<Font> fonts;
fonts.push_back(
Font("Arial", 18).Derive(0, Font::ITALIC, Font::Weight::NORMAL));
fonts.push_back(Font("Courier New", 18)
.Derive(0, Font::ITALIC, Font::Weight::NORMAL));
FontList font_list = FontList(fonts);
FontList derived = font_list.DeriveWithSizeDelta(-5);
const std::vector<Font>& derived_fonts = derived.GetFonts();
EXPECT_EQ(2U, derived_fonts.size());
EXPECT_EQ("Arial|13|italic|normal", FontToString(derived_fonts[0]));
EXPECT_EQ("Courier New|13|italic|normal", FontToString(derived_fonts[1]));
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_GetHeight_GetBaseline DISABLED_Fonts_GetHeight_GetBaseline
#else
#define MAYBE_Fonts_GetHeight_GetBaseline Fonts_GetHeight_GetBaseline
#endif
TEST(FontListTest, MAYBE_Fonts_GetHeight_GetBaseline) {
// If a font list has only one font, the height and baseline must be the same.
Font font1("Arial", 16);
ASSERT_EQ("arial", base::ToLowerASCII(font1.GetActualFontNameForTesting()));
FontList font_list1("Arial, 16px");
EXPECT_EQ(font1.GetHeight(), font_list1.GetHeight());
EXPECT_EQ(font1.GetBaseline(), font_list1.GetBaseline());
// If there are two different fonts, the font list returns the max value
// for the baseline (ascent) and height.
Font font2(kCJKFontName, 16);
ASSERT_EQ(base::ToLowerASCII(kCJKFontName),
base::ToLowerASCII(font2.GetActualFontNameForTesting()));
EXPECT_NE(font1.GetBaseline(), font2.GetBaseline());
// TODO(ananta): Find a size and font pair with reliably distinct descents.
EXPECT_NE(font1.GetHeight(), font2.GetHeight());
std::vector<Font> fonts;
fonts.push_back(font1);
fonts.push_back(font2);
FontList font_list_mix(fonts);
// ascent of FontList == max(ascent of Fonts)
EXPECT_EQ(std::max(font1.GetBaseline(), font2.GetBaseline()),
font_list_mix.GetBaseline());
// descent of FontList == max(descent of Fonts)
EXPECT_EQ(std::max(font1.GetHeight() - font1.GetBaseline(),
font2.GetHeight() - font2.GetBaseline()),
font_list_mix.GetHeight() - font_list_mix.GetBaseline());
}
// TODO(489354): Enable this on android.
#if defined(OS_ANDROID)
#define MAYBE_Fonts_DeriveWithHeightUpperBound \
DISABLED_Fonts_DeriveWithHeightUpperBound
#else
#define MAYBE_Fonts_DeriveWithHeightUpperBound Fonts_DeriveWithHeightUpperBound
#endif
TEST(FontListTest, MAYBE_Fonts_DeriveWithHeightUpperBound) {
std::vector<Font> fonts;
fonts.push_back(Font("Arial", 18));
fonts.push_back(Font("Sans serif", 18));
fonts.push_back(Font(kSymbolFontName, 18));
FontList font_list = FontList(fonts);
// A smaller upper bound should derive a font list with a smaller height.
const int height_1 = font_list.GetHeight() - 5;
FontList derived_1 = font_list.DeriveWithHeightUpperBound(height_1);
EXPECT_LE(derived_1.GetHeight(), height_1);
EXPECT_LT(derived_1.GetHeight(), font_list.GetHeight());
EXPECT_LT(derived_1.GetFontSize(), font_list.GetFontSize());
// A larger upper bound should not change the height of the font list.
const int height_2 = font_list.GetHeight() + 5;
FontList derived_2 = font_list.DeriveWithHeightUpperBound(height_2);
EXPECT_LE(derived_2.GetHeight(), height_2);
EXPECT_EQ(font_list.GetHeight(), derived_2.GetHeight());
EXPECT_EQ(font_list.GetFontSize(), derived_2.GetFontSize());
}
} // namespace gfx