mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Support user-provided font-fallback. (#7241)
* Support user-provided font-fallback. * Use tonic to pass to native * Handle font families as a fallback vector in LibTxt * Fix docs * Concatentate fontFamily lists in dart before passing to engine * Fix formatting * Reworked font family matching to search all managers * Fix formatting * Proper toString null checking to keep format consistent * Formatting * Move _listEquals out of textstyle as it is not specific to TextStyle and will later be used for paragraphStyle too
This commit is contained in:
parent
526b4bc357
commit
215ca15600
@ -3802,23 +3802,6 @@ class Shadow {
|
||||
@override
|
||||
int get hashCode => hashValues(color, offset, blurRadius);
|
||||
|
||||
/// Determines if lists [a] and [b] are deep equivalent.
|
||||
///
|
||||
/// Returns true if the lists are both null, or if they are both non-null, have
|
||||
/// the same length, and contain the same Shadows in the same order. Returns
|
||||
/// false otherwise.
|
||||
static bool _shadowsListEquals(List<Shadow> a, List<Shadow> b) {
|
||||
// Compare _shadows
|
||||
if (a == null)
|
||||
return b == null;
|
||||
if (b == null || a.length != b.length)
|
||||
return false;
|
||||
for (int index = 0; index < a.length; ++index)
|
||||
if (a[index] != b[index])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Serialize [shadows] into ByteData. The format is a single uint_32_t at
|
||||
// the beginning indicating the number of shadows, followed by _kBytesPerShadow
|
||||
// bytes for each shadow.
|
||||
|
||||
@ -218,6 +218,23 @@ enum TextDecorationStyle {
|
||||
wavy
|
||||
}
|
||||
|
||||
/// Determines if lists [a] and [b] are deep equivalent.
|
||||
///
|
||||
/// Returns true if the lists are both null, or if they are both non-null, have
|
||||
/// the same length, and contain the same elements in the same order. Returns
|
||||
/// false otherwise.
|
||||
bool _listEquals<T>(List<T> a, List<T> b) {
|
||||
if (a == null)
|
||||
return b == null;
|
||||
if (b == null || a.length != b.length)
|
||||
return false;
|
||||
for (int index = 0; index < a.length; index += 1) {
|
||||
if (a[index] != b[index])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This encoding must match the C++ version of ParagraphBuilder::pushStyle.
|
||||
//
|
||||
// The encoded array buffer has 8 elements.
|
||||
@ -252,6 +269,7 @@ Int32List _encodeTextStyle(
|
||||
FontStyle fontStyle,
|
||||
TextBaseline textBaseline,
|
||||
String fontFamily,
|
||||
List<String> fontFamilyFallback,
|
||||
double fontSize,
|
||||
double letterSpacing,
|
||||
double wordSpacing,
|
||||
@ -290,7 +308,7 @@ Int32List _encodeTextStyle(
|
||||
result[0] |= 1 << 7;
|
||||
result[7] = textBaseline.index;
|
||||
}
|
||||
if (fontFamily != null) {
|
||||
if (fontFamily != null || (fontFamilyFallback != null && fontFamilyFallback.isNotEmpty)) {
|
||||
result[0] |= 1 << 8;
|
||||
// Passed separately to native.
|
||||
}
|
||||
@ -339,7 +357,15 @@ class TextStyle {
|
||||
/// * `decorationStyle`: The style in which to paint the text decorations (e.g., dashed).
|
||||
/// * `fontWeight`: The typeface thickness to use when painting the text (e.g., bold).
|
||||
/// * `fontStyle`: The typeface variant to use when drawing the letters (e.g., italics).
|
||||
/// * `fontFamily`: The name of the font to use when painting the text (e.g., Roboto).
|
||||
/// * `fontFamily`: The name of the font to use when painting the text (e.g., Roboto). If a `fontFamilyFallback` is
|
||||
/// provided and `fontFamily` is not, then the first font family in `fontFamilyFallback` will take the postion of
|
||||
/// the preferred font family. When a higher priority font cannot be found or does not contain a glyph, a lower
|
||||
/// priority font will be used.
|
||||
/// * `fontFamilyFallback`: An ordered list of the names of the fonts to fallback on when a glyph cannot
|
||||
/// be found in a higher priority font. When the `fontFamily` is null, the first font family in this list
|
||||
/// is used as the preferred font. Internally, the 'fontFamily` is concatenated to the front of this list.
|
||||
/// When no font family is provided through 'fontFamilyFallback' (null or empty) or `fontFamily`, then the
|
||||
/// platform default font will be used.
|
||||
/// * `fontSize`: The size of glyphs (in logical pixels) to use when painting the text.
|
||||
/// * `letterSpacing`: The amount of space (in logical pixels) to add between each letter.
|
||||
/// * `wordSpacing`: The amount of space (in logical pixels) to add at each sequence of white-space (i.e. between each word).
|
||||
@ -357,6 +383,7 @@ class TextStyle {
|
||||
FontStyle fontStyle,
|
||||
TextBaseline textBaseline,
|
||||
String fontFamily,
|
||||
List<String> fontFamilyFallback,
|
||||
double fontSize,
|
||||
double letterSpacing,
|
||||
double wordSpacing,
|
||||
@ -378,6 +405,7 @@ class TextStyle {
|
||||
fontStyle,
|
||||
textBaseline,
|
||||
fontFamily,
|
||||
fontFamilyFallback,
|
||||
fontSize,
|
||||
letterSpacing,
|
||||
wordSpacing,
|
||||
@ -388,6 +416,7 @@ class TextStyle {
|
||||
shadows,
|
||||
),
|
||||
_fontFamily = fontFamily ?? '',
|
||||
_fontFamilyFallback = fontFamilyFallback,
|
||||
_fontSize = fontSize,
|
||||
_letterSpacing = letterSpacing,
|
||||
_wordSpacing = wordSpacing,
|
||||
@ -399,6 +428,7 @@ class TextStyle {
|
||||
|
||||
final Int32List _encoded;
|
||||
final String _fontFamily;
|
||||
final List<String> _fontFamilyFallback;
|
||||
final double _fontSize;
|
||||
final double _letterSpacing;
|
||||
final double _wordSpacing;
|
||||
@ -428,33 +458,39 @@ class TextStyle {
|
||||
if (_encoded[index] != typedOther._encoded[index])
|
||||
return false;
|
||||
}
|
||||
if (!Shadow._shadowsListEquals(_shadows, typedOther._shadows))
|
||||
if (!_listEquals<Shadow>(_shadows, typedOther._shadows))
|
||||
return false;
|
||||
if (!_listEquals<String>(_fontFamilyFallback, typedOther._fontFamilyFallback))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background, _foreground);
|
||||
int get hashCode => hashValues(hashList(_encoded), _fontFamily, _fontFamilyFallback, _fontSize, _letterSpacing, _wordSpacing, _height, _locale, _background, _foreground, _shadows);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TextStyle('
|
||||
'color: ${ _encoded[0] & 0x00002 == 0x00002 ? new Color(_encoded[1]) : "unspecified"}, '
|
||||
'decoration: ${ _encoded[0] & 0x00004 == 0x00004 ? new TextDecoration._(_encoded[2]) : "unspecified"}, '
|
||||
'decorationColor: ${_encoded[0] & 0x00008 == 0x00008 ? new Color(_encoded[3]) : "unspecified"}, '
|
||||
'decorationStyle: ${_encoded[0] & 0x00010 == 0x00010 ? TextDecorationStyle.values[_encoded[4]] : "unspecified"}, '
|
||||
'fontWeight: ${ _encoded[0] & 0x00020 == 0x00020 ? FontWeight.values[_encoded[5]] : "unspecified"}, '
|
||||
'fontStyle: ${ _encoded[0] & 0x00040 == 0x00040 ? FontStyle.values[_encoded[6]] : "unspecified"}, '
|
||||
'textBaseline: ${ _encoded[0] & 0x00080 == 0x00080 ? TextBaseline.values[_encoded[7]] : "unspecified"}, '
|
||||
'fontFamily: ${ _encoded[0] & 0x00100 == 0x00100 ? _fontFamily : "unspecified"}, '
|
||||
'fontSize: ${ _encoded[0] & 0x00200 == 0x00200 ? _fontSize : "unspecified"}, '
|
||||
'letterSpacing: ${ _encoded[0] & 0x00400 == 0x00400 ? "${_letterSpacing}x" : "unspecified"}, '
|
||||
'wordSpacing: ${ _encoded[0] & 0x00800 == 0x00800 ? "${_wordSpacing}x" : "unspecified"}, '
|
||||
'height: ${ _encoded[0] & 0x01000 == 0x01000 ? "${_height}x" : "unspecified"}, '
|
||||
'locale: ${ _encoded[0] & 0x02000 == 0x02000 ? _locale : "unspecified"}, '
|
||||
'background: ${ _encoded[0] & 0x04000 == 0x04000 ? _background : "unspecified"}, '
|
||||
'foreground: ${ _encoded[0] & 0x08000 == 0x08000 ? _foreground : "unspecified"}, '
|
||||
'shadows: ${ _encoded[0] & 0x10000 == 0x10000 ? _shadows : "unspecified"}'
|
||||
'color: ${ _encoded[0] & 0x00002 == 0x00002 ? new Color(_encoded[1]) : "unspecified"}, '
|
||||
'decoration: ${ _encoded[0] & 0x00004 == 0x00004 ? new TextDecoration._(_encoded[2]) : "unspecified"}, '
|
||||
'decorationColor: ${ _encoded[0] & 0x00008 == 0x00008 ? new Color(_encoded[3]) : "unspecified"}, '
|
||||
'decorationStyle: ${ _encoded[0] & 0x00010 == 0x00010 ? TextDecorationStyle.values[_encoded[4]] : "unspecified"}, '
|
||||
'fontWeight: ${ _encoded[0] & 0x00020 == 0x00020 ? FontWeight.values[_encoded[5]] : "unspecified"}, '
|
||||
'fontStyle: ${ _encoded[0] & 0x00040 == 0x00040 ? FontStyle.values[_encoded[6]] : "unspecified"}, '
|
||||
'textBaseline: ${ _encoded[0] & 0x00080 == 0x00080 ? TextBaseline.values[_encoded[7]] : "unspecified"}, '
|
||||
'fontFamily: ${ _encoded[0] & 0x00100 == 0x00100
|
||||
&& _fontFamily != null ? _fontFamily : "unspecified"}, '
|
||||
'fontFamilyFallback: ${_encoded[0] & 0x00100 == 0x00100
|
||||
&& _fontFamilyFallback != null
|
||||
&& _fontFamilyFallback.isNotEmpty ? _fontFamilyFallback : "unspecified"}, '
|
||||
'fontSize: ${ _encoded[0] & 0x00200 == 0x00200 ? _fontSize : "unspecified"}, '
|
||||
'letterSpacing: ${ _encoded[0] & 0x00400 == 0x00400 ? "${_letterSpacing}x" : "unspecified"}, '
|
||||
'wordSpacing: ${ _encoded[0] & 0x00800 == 0x00800 ? "${_wordSpacing}x" : "unspecified"}, '
|
||||
'height: ${ _encoded[0] & 0x01000 == 0x01000 ? "${_height}x" : "unspecified"}, '
|
||||
'locale: ${ _encoded[0] & 0x02000 == 0x02000 ? _locale : "unspecified"}, '
|
||||
'background: ${ _encoded[0] & 0x04000 == 0x04000 ? _background : "unspecified"}, '
|
||||
'foreground: ${ _encoded[0] & 0x08000 == 0x08000 ? _foreground : "unspecified"}, '
|
||||
'shadows: ${ _encoded[0] & 0x10000 == 0x10000 ? _shadows : "unspecified"}'
|
||||
')';
|
||||
}
|
||||
}
|
||||
@ -1173,8 +1209,15 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 {
|
||||
/// Applies the given style to the added text until [pop] is called.
|
||||
///
|
||||
/// See [pop] for details.
|
||||
void pushStyle(TextStyle style) => _pushStyle(style._encoded, style._fontFamily, style._fontSize, style._letterSpacing, style._wordSpacing, style._height, _encodeLocale(style._locale), style._background?._objects, style._background?._data, style._foreground?._objects, style._foreground?._data, Shadow._encodeShadows(style._shadows));
|
||||
void _pushStyle(Int32List encoded, String fontFamily, double fontSize, double letterSpacing, double wordSpacing, double height, String locale, List<dynamic> backgroundObjects, ByteData backgroundData, List<dynamic> foregroundObjects, ByteData foregroundData, ByteData shadowsData) native 'ParagraphBuilder_pushStyle';
|
||||
void pushStyle(TextStyle style) {
|
||||
final List<String> fullFontFamilies = <String>[];
|
||||
if (style._fontFamily != null)
|
||||
fullFontFamilies.add(style._fontFamily);
|
||||
if (style._fontFamilyFallback != null)
|
||||
fullFontFamilies.addAll(style._fontFamilyFallback);
|
||||
_pushStyle(style._encoded, fullFontFamilies, style._fontSize, style._letterSpacing, style._wordSpacing, style._height, _encodeLocale(style._locale), style._background?._objects, style._background?._data, style._foreground?._objects, style._foreground?._data, Shadow._encodeShadows(style._shadows));
|
||||
}
|
||||
void _pushStyle(Int32List encoded, List<dynamic> fontFamilies, double fontSize, double letterSpacing, double wordSpacing, double height, String locale, List<dynamic> backgroundObjects, ByteData backgroundData, List<dynamic> foregroundObjects, ByteData foregroundData, ByteData shadowsData) native 'ParagraphBuilder_pushStyle';
|
||||
|
||||
static String _encodeLocale(Locale locale) => locale?.toString() ?? '';
|
||||
|
||||
|
||||
@ -202,7 +202,7 @@ void decodeTextShadows(Dart_Handle shadows_data,
|
||||
}
|
||||
|
||||
void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
|
||||
const std::string& fontFamily,
|
||||
const std::vector<std::string>& fontFamilies,
|
||||
double fontSize,
|
||||
double letterSpacing,
|
||||
double wordSpacing,
|
||||
@ -243,8 +243,8 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
|
||||
// property wasn't wired up either.
|
||||
}
|
||||
|
||||
if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontFamilyMask |
|
||||
tsFontSizeMask | tsLetterSpacingMask | tsWordSpacingMask)) {
|
||||
if (mask & (tsFontWeightMask | tsFontStyleMask | tsFontSizeMask |
|
||||
tsLetterSpacingMask | tsWordSpacingMask)) {
|
||||
if (mask & tsFontWeightMask)
|
||||
style.font_weight =
|
||||
static_cast<txt::FontWeight>(encoded[tsFontWeightIndex]);
|
||||
@ -252,9 +252,6 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
|
||||
if (mask & tsFontStyleMask)
|
||||
style.font_style = static_cast<txt::FontStyle>(encoded[tsFontStyleIndex]);
|
||||
|
||||
if (mask & tsFontFamilyMask)
|
||||
style.font_family = fontFamily;
|
||||
|
||||
if (mask & tsFontSizeMask)
|
||||
style.font_size = fontSize;
|
||||
|
||||
@ -293,6 +290,11 @@ void ParagraphBuilder::pushStyle(tonic::Int32List& encoded,
|
||||
decodeTextShadows(shadows_data, style.text_shadows);
|
||||
}
|
||||
|
||||
if (mask & tsFontFamilyMask) {
|
||||
style.font_families.insert(style.font_families.end(), fontFamilies.begin(),
|
||||
fontFamilies.end());
|
||||
}
|
||||
|
||||
m_paragraphBuilder->PushStyle(style);
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ class ParagraphBuilder : public RefCountedDartWrappable<ParagraphBuilder> {
|
||||
~ParagraphBuilder() override;
|
||||
|
||||
void pushStyle(tonic::Int32List& encoded,
|
||||
const std::string& fontFamily,
|
||||
const std::vector<std::string>& fontFamilies,
|
||||
double fontSize,
|
||||
double letterSpacing,
|
||||
double wordSpacing,
|
||||
|
||||
111
third_party/txt/src/txt/font_collection.cc
vendored
111
third_party/txt/src/txt/font_collection.cc
vendored
@ -16,6 +16,7 @@
|
||||
|
||||
#include "font_collection.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@ -36,14 +37,24 @@ const std::shared_ptr<minikin::FontFamily> g_null_family;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
FontCollection::FamilyKey::FamilyKey(const std::vector<std::string>& families,
|
||||
const std::string& loc) {
|
||||
locale = loc;
|
||||
|
||||
std::stringstream stream;
|
||||
for_each(families.begin(), families.end(),
|
||||
[&stream](const std::string& str) { stream << str << ','; });
|
||||
font_families = stream.str();
|
||||
}
|
||||
|
||||
bool FontCollection::FamilyKey::operator==(
|
||||
const FontCollection::FamilyKey& other) const {
|
||||
return font_family == other.font_family && locale == other.locale;
|
||||
return font_families == other.font_families && locale == other.locale;
|
||||
}
|
||||
|
||||
size_t FontCollection::FamilyKey::Hasher::operator()(
|
||||
const FontCollection::FamilyKey& key) const {
|
||||
return std::hash<std::string>()(key.font_family) ^
|
||||
return std::hash<std::string>()(key.font_families) ^
|
||||
std::hash<std::string>()(key.locale);
|
||||
}
|
||||
|
||||
@ -111,58 +122,72 @@ void FontCollection::DisableFontFallback() {
|
||||
}
|
||||
|
||||
std::shared_ptr<minikin::FontCollection>
|
||||
FontCollection::GetMinikinFontCollectionForFamily(
|
||||
const std::string& font_family,
|
||||
FontCollection::GetMinikinFontCollectionForFamilies(
|
||||
const std::vector<std::string>& font_families,
|
||||
const std::string& locale) {
|
||||
// Look inside the font collections cache first.
|
||||
FamilyKey family_key(font_family, locale);
|
||||
FamilyKey family_key(font_families, locale);
|
||||
auto cached = font_collections_cache_.find(family_key);
|
||||
if (cached != font_collections_cache_.end()) {
|
||||
return cached->second;
|
||||
}
|
||||
|
||||
for (sk_sp<SkFontMgr>& manager : GetFontManagerOrder()) {
|
||||
std::shared_ptr<minikin::FontFamily> minikin_family =
|
||||
CreateMinikinFontFamily(manager, font_family);
|
||||
if (!minikin_family)
|
||||
continue;
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>> minikin_families;
|
||||
|
||||
// Create a vector of font families for the Minikin font collection.
|
||||
std::vector<std::shared_ptr<minikin::FontFamily>> minikin_families = {
|
||||
minikin_family,
|
||||
};
|
||||
if (enable_font_fallback_) {
|
||||
for (std::string fallback_family : fallback_fonts_for_locale_[locale]) {
|
||||
auto it = fallback_fonts_.find(fallback_family);
|
||||
if (it != fallback_fonts_.end()) {
|
||||
minikin_families.push_back(it->second);
|
||||
}
|
||||
// Search for all user provided font families.
|
||||
for (size_t fallback_index = 0; fallback_index < font_families.size();
|
||||
fallback_index++) {
|
||||
std::shared_ptr<minikin::FontFamily> minikin_family =
|
||||
FindFontFamilyInManagers(font_families[fallback_index]);
|
||||
if (minikin_family != nullptr) {
|
||||
minikin_families.push_back(minikin_family);
|
||||
}
|
||||
}
|
||||
// Search for default font family if no user font families were found.
|
||||
if (minikin_families.empty()) {
|
||||
const auto default_font_family = GetDefaultFontFamily();
|
||||
std::shared_ptr<minikin::FontFamily> minikin_family =
|
||||
FindFontFamilyInManagers(default_font_family);
|
||||
if (minikin_family != nullptr) {
|
||||
minikin_families.push_back(minikin_family);
|
||||
}
|
||||
}
|
||||
// Default font family also not found. We fail to get a FontCollection.
|
||||
if (minikin_families.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (enable_font_fallback_) {
|
||||
for (std::string fallback_family : fallback_fonts_for_locale_[locale]) {
|
||||
auto it = fallback_fonts_.find(fallback_family);
|
||||
if (it != fallback_fonts_.end()) {
|
||||
minikin_families.push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the minikin font collection.
|
||||
auto font_collection =
|
||||
std::make_shared<minikin::FontCollection>(std::move(minikin_families));
|
||||
if (enable_font_fallback_) {
|
||||
font_collection->set_fallback_font_provider(
|
||||
std::make_unique<TxtFallbackFontProvider>(shared_from_this()));
|
||||
}
|
||||
|
||||
// Cache the font collection for future queries.
|
||||
font_collections_cache_[family_key] = font_collection;
|
||||
|
||||
return font_collection;
|
||||
}
|
||||
// Create the minikin font collection.
|
||||
auto font_collection =
|
||||
std::make_shared<minikin::FontCollection>(std::move(minikin_families));
|
||||
if (enable_font_fallback_) {
|
||||
font_collection->set_fallback_font_provider(
|
||||
std::make_unique<TxtFallbackFontProvider>(shared_from_this()));
|
||||
}
|
||||
|
||||
const auto default_font_family = GetDefaultFontFamily();
|
||||
if (font_family != default_font_family) {
|
||||
std::shared_ptr<minikin::FontCollection> default_collection =
|
||||
GetMinikinFontCollectionForFamily(default_font_family, "");
|
||||
font_collections_cache_[family_key] = default_collection;
|
||||
return default_collection;
|
||||
}
|
||||
// Cache the font collection for future queries.
|
||||
font_collections_cache_[family_key] = font_collection;
|
||||
|
||||
// No match found in any of our font managers.
|
||||
return font_collection;
|
||||
}
|
||||
|
||||
std::shared_ptr<minikin::FontFamily> FontCollection::FindFontFamilyInManagers(
|
||||
const std::string& family_name) {
|
||||
// Search for the font family in each font manager.
|
||||
for (sk_sp<SkFontMgr>& manager : GetFontManagerOrder()) {
|
||||
std::shared_ptr<minikin::FontFamily> minikin_family =
|
||||
CreateMinikinFontFamily(manager, family_name);
|
||||
if (!minikin_family)
|
||||
continue;
|
||||
return minikin_family;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -254,8 +279,8 @@ FontCollection::GetFallbackFontFamily(const sk_sp<SkFontMgr>& manager,
|
||||
auto insert_it =
|
||||
fallback_fonts_.insert(std::make_pair(family_name, minikin_family));
|
||||
|
||||
// Clear the cache to force creation of new font collections that will include
|
||||
// this fallback font.
|
||||
// Clear the cache to force creation of new font collections that will
|
||||
// include this fallback font.
|
||||
font_collections_cache_.clear();
|
||||
|
||||
return insert_it.first->second;
|
||||
|
||||
13
third_party/txt/src/txt/font_collection.h
vendored
13
third_party/txt/src/txt/font_collection.h
vendored
@ -45,8 +45,8 @@ class FontCollection : public std::enable_shared_from_this<FontCollection> {
|
||||
void SetDynamicFontManager(sk_sp<SkFontMgr> font_manager);
|
||||
void SetTestFontManager(sk_sp<SkFontMgr> font_manager);
|
||||
|
||||
std::shared_ptr<minikin::FontCollection> GetMinikinFontCollectionForFamily(
|
||||
const std::string& family,
|
||||
std::shared_ptr<minikin::FontCollection> GetMinikinFontCollectionForFamilies(
|
||||
const std::vector<std::string>& font_families,
|
||||
const std::string& locale);
|
||||
|
||||
// Provides a FontFamily that contains glyphs for ch. This caches previously
|
||||
@ -61,10 +61,10 @@ class FontCollection : public std::enable_shared_from_this<FontCollection> {
|
||||
|
||||
private:
|
||||
struct FamilyKey {
|
||||
FamilyKey(const std::string& family, const std::string& loc)
|
||||
: font_family(family), locale(loc) {}
|
||||
FamilyKey(const std::vector<std::string>& families, const std::string& loc);
|
||||
|
||||
std::string font_family;
|
||||
// Concatenated string with all font families.
|
||||
std::string font_families;
|
||||
std::string locale;
|
||||
|
||||
bool operator==(const FamilyKey& other) const;
|
||||
@ -100,6 +100,9 @@ class FontCollection : public std::enable_shared_from_this<FontCollection> {
|
||||
|
||||
std::vector<sk_sp<SkFontMgr>> GetFontManagerOrder() const;
|
||||
|
||||
std::shared_ptr<minikin::FontFamily> FindFontFamilyInManagers(
|
||||
const std::string& family_name);
|
||||
|
||||
std::shared_ptr<minikin::FontFamily> CreateMinikinFontFamily(
|
||||
const sk_sp<SkFontMgr>& manager,
|
||||
const std::string& family_name);
|
||||
|
||||
9
third_party/txt/src/txt/paragraph.cc
vendored
9
third_party/txt/src/txt/paragraph.cc
vendored
@ -290,7 +290,10 @@ bool Paragraph::ComputeLineBreaks() {
|
||||
GetMinikinFontCollectionForStyle(run.style);
|
||||
if (collection == nullptr) {
|
||||
FML_LOG(INFO) << "Could not find font collection for family \""
|
||||
<< run.style.font_family << "\".";
|
||||
<< (run.style.font_families.empty()
|
||||
? ""
|
||||
: run.style.font_families[0])
|
||||
<< "\".";
|
||||
return false;
|
||||
}
|
||||
size_t run_start = std::max(run.start, block_start) - block_start;
|
||||
@ -900,8 +903,8 @@ Paragraph::GetMinikinFontCollectionForStyle(const TextStyle& style) {
|
||||
}
|
||||
}
|
||||
|
||||
return font_collection_->GetMinikinFontCollectionForFamily(style.font_family,
|
||||
locale);
|
||||
return font_collection_->GetMinikinFontCollectionForFamilies(
|
||||
style.font_families, locale);
|
||||
}
|
||||
|
||||
sk_sp<SkTypeface> Paragraph::GetDefaultSkiaTypeface(const TextStyle& style) {
|
||||
|
||||
1
third_party/txt/src/txt/paragraph.h
vendored
1
third_party/txt/src/txt/paragraph.h
vendored
@ -226,6 +226,7 @@ class Paragraph {
|
||||
FRIEND_TEST(ParagraphTest, UnderlineShiftParagraph);
|
||||
FRIEND_TEST(ParagraphTest, SimpleShadow);
|
||||
FRIEND_TEST(ParagraphTest, ComplexShadow);
|
||||
FRIEND_TEST(ParagraphTest, FontFallbackParagraph);
|
||||
|
||||
// Starting data to layout.
|
||||
std::vector<uint16_t> text_;
|
||||
|
||||
4
third_party/txt/src/txt/paragraph_style.cc
vendored
4
third_party/txt/src/txt/paragraph_style.cc
vendored
@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "paragraph_style.h"
|
||||
|
||||
namespace txt {
|
||||
@ -22,7 +24,7 @@ TextStyle ParagraphStyle::GetTextStyle() const {
|
||||
TextStyle result;
|
||||
result.font_weight = font_weight;
|
||||
result.font_style = font_style;
|
||||
result.font_family = font_family;
|
||||
result.font_families = std::vector<std::string>({font_family});
|
||||
result.font_size = font_size;
|
||||
result.locale = locale;
|
||||
result.height = line_height;
|
||||
|
||||
1
third_party/txt/src/txt/styled_runs.h
vendored
1
third_party/txt/src/txt/styled_runs.h
vendored
@ -81,6 +81,7 @@ class StyledRuns {
|
||||
FRIEND_TEST(ParagraphTest, Ellipsize);
|
||||
FRIEND_TEST(ParagraphTest, SimpleShadow);
|
||||
FRIEND_TEST(ParagraphTest, ComplexShadow);
|
||||
FRIEND_TEST(ParagraphTest, FontFallbackParagraph);
|
||||
|
||||
struct IndexedRun {
|
||||
size_t style_index = 0;
|
||||
|
||||
9
third_party/txt/src/txt/text_style.cc
vendored
9
third_party/txt/src/txt/text_style.cc
vendored
@ -22,7 +22,8 @@
|
||||
|
||||
namespace txt {
|
||||
|
||||
TextStyle::TextStyle() : font_family(GetDefaultFontFamily()) {}
|
||||
TextStyle::TextStyle()
|
||||
: font_families(std::vector<std::string>(1, GetDefaultFontFamily())) {}
|
||||
|
||||
bool TextStyle::equals(const TextStyle& other) const {
|
||||
if (color != other.color)
|
||||
@ -39,8 +40,6 @@ bool TextStyle::equals(const TextStyle& other) const {
|
||||
return false;
|
||||
if (font_style != other.font_style)
|
||||
return false;
|
||||
if (font_family != other.font_family)
|
||||
return false;
|
||||
if (letter_spacing != other.letter_spacing)
|
||||
return false;
|
||||
if (word_spacing != other.word_spacing)
|
||||
@ -53,6 +52,10 @@ bool TextStyle::equals(const TextStyle& other) const {
|
||||
return false;
|
||||
if (text_shadows.size() != other.text_shadows.size())
|
||||
return false;
|
||||
for (size_t font_index = 0; font_index < font_families.size(); ++font_index) {
|
||||
if (font_families[font_index] != other.font_families[font_index])
|
||||
return false;
|
||||
}
|
||||
for (size_t shadow_index = 0; shadow_index < text_shadows.size();
|
||||
++shadow_index) {
|
||||
if (text_shadows[shadow_index] != other.text_shadows[shadow_index])
|
||||
|
||||
4
third_party/txt/src/txt/text_style.h
vendored
4
third_party/txt/src/txt/text_style.h
vendored
@ -43,7 +43,9 @@ class TextStyle {
|
||||
FontWeight font_weight = FontWeight::w400;
|
||||
FontStyle font_style = FontStyle::normal;
|
||||
TextBaseline text_baseline = TextBaseline::kAlphabetic;
|
||||
std::string font_family;
|
||||
// An ordered list of fonts in order of priority. The first font is more
|
||||
// highly preferred than the last font.
|
||||
std::vector<std::string> font_families;
|
||||
double font_size = 14.0;
|
||||
double letter_spacing = 0.0;
|
||||
double word_spacing = 0.0;
|
||||
|
||||
174
third_party/txt/tests/paragraph_unittests.cc
vendored
174
third_party/txt/tests/paragraph_unittests.cc
vendored
@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "render_test.h"
|
||||
#include "third_party/icu/source/common/unicode/unistr.h"
|
||||
@ -40,7 +42,11 @@ TEST_F(ParagraphTest, SimpleParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
// We must supply a font here, as the default is Arial, and we do not
|
||||
// include Arial in our test fonts as it is proprietary. We want it to
|
||||
// be Arial default though as it is one of the most common fonts on host
|
||||
// platforms. On real devices/apps, Arial should be able to be resolved.
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
builder.AddText(u16_text);
|
||||
@ -73,7 +79,7 @@ TEST_F(ParagraphTest, SimpleRedParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorRED;
|
||||
builder.PushStyle(text_style);
|
||||
|
||||
@ -127,8 +133,9 @@ TEST_F(ParagraphTest, RainbowParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style1;
|
||||
text_style1.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style1.color = SK_ColorRED;
|
||||
text_style1.font_family = "Roboto";
|
||||
|
||||
builder.PushStyle(text_style1);
|
||||
|
||||
builder.AddText(u16_text1);
|
||||
@ -139,7 +146,7 @@ TEST_F(ParagraphTest, RainbowParagraph) {
|
||||
text_style2.word_spacing = 30;
|
||||
text_style2.font_weight = txt::FontWeight::w600;
|
||||
text_style2.color = SK_ColorGREEN;
|
||||
text_style2.font_family = "Roboto";
|
||||
text_style2.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style2.decoration = TextDecoration::kUnderline |
|
||||
TextDecoration::kOverline |
|
||||
TextDecoration::kLineThrough;
|
||||
@ -149,7 +156,7 @@ TEST_F(ParagraphTest, RainbowParagraph) {
|
||||
builder.AddText(u16_text2);
|
||||
|
||||
txt::TextStyle text_style3;
|
||||
text_style3.font_family = "Homemade Apple";
|
||||
text_style3.font_families = std::vector<std::string>(1, "Homemade Apple");
|
||||
builder.PushStyle(text_style3);
|
||||
|
||||
builder.AddText(u16_text3);
|
||||
@ -157,7 +164,7 @@ TEST_F(ParagraphTest, RainbowParagraph) {
|
||||
txt::TextStyle text_style4;
|
||||
text_style4.font_size = 14;
|
||||
text_style4.color = SK_ColorBLUE;
|
||||
text_style4.font_family = "Roboto";
|
||||
text_style4.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style4.decoration = TextDecoration::kUnderline |
|
||||
TextDecoration::kOverline |
|
||||
TextDecoration::kLineThrough;
|
||||
@ -174,7 +181,6 @@ TEST_F(ParagraphTest, RainbowParagraph) {
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 0, 0);
|
||||
|
||||
u16_text1 += u16_text2 + u16_text3 + u16_text4;
|
||||
@ -233,7 +239,7 @@ TEST_F(ParagraphTest, BoldParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 60;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = txt::FontWeight::w900;
|
||||
@ -289,7 +295,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeftAlignParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
@ -386,7 +392,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(RightAlignParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
@ -495,7 +501,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(CenterAlignParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
@ -603,7 +609,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyAlignParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 5;
|
||||
@ -670,7 +676,7 @@ TEST_F(ParagraphTest, DecorationsParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 5;
|
||||
@ -748,7 +754,7 @@ TEST_F(ParagraphTest, ItalicsParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorRED;
|
||||
text_style.font_size = 10;
|
||||
builder.PushStyle(text_style);
|
||||
@ -795,7 +801,7 @@ TEST_F(ParagraphTest, ChineseParagraph) {
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.font_size = 35;
|
||||
text_style.letter_spacing = 2;
|
||||
text_style.font_family = "Source Han Serif CN";
|
||||
text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN");
|
||||
text_style.decoration = TextDecoration::kUnderline |
|
||||
TextDecoration::kOverline |
|
||||
TextDecoration::kLineThrough;
|
||||
@ -840,7 +846,7 @@ TEST_F(ParagraphTest, DISABLED_ArabicParagraph) {
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.font_size = 35;
|
||||
text_style.letter_spacing = 2;
|
||||
text_style.font_family = "Katibeh";
|
||||
text_style.font_families = std::vector<std::string>(1, "Katibeh");
|
||||
text_style.decoration = TextDecoration::kUnderline |
|
||||
TextDecoration::kOverline |
|
||||
TextDecoration::kLineThrough;
|
||||
@ -887,7 +893,7 @@ TEST_F(ParagraphTest, GetGlyphPositionAtCoordinateParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
@ -955,7 +961,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1085,7 +1091,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeTight)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Noto Sans CJK JP";
|
||||
text_style.font_families = std::vector<std::string>(1, "Noto Sans CJK JP");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1179,7 +1185,8 @@ TEST_F(ParagraphTest,
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
// text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1330,7 +1337,7 @@ TEST_F(ParagraphTest,
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1481,7 +1488,7 @@ TEST_F(ParagraphTest,
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1626,7 +1633,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(GetRectsForRangeCenterParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1734,7 +1741,7 @@ TEST_F(ParagraphTest,
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.font_weight = FontWeight::w500;
|
||||
@ -1874,7 +1881,7 @@ TEST_F(ParagraphTest, GetWordBoundaryParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 52;
|
||||
text_style.letter_spacing = 1.19039;
|
||||
text_style.word_spacing = 5;
|
||||
@ -1980,7 +1987,7 @@ TEST_F(ParagraphTest, SpacingParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 50;
|
||||
text_style.letter_spacing = 20;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2069,7 +2076,7 @@ TEST_F(ParagraphTest, LongWordParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 31;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2106,7 +2113,7 @@ TEST_F(ParagraphTest, KernScaleParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Droid Serif";
|
||||
text_style.font_families = std::vector<std::string>(1, "Droid Serif");
|
||||
text_style.font_size = 100 / scale;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2148,7 +2155,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(NewlineParagraph)) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 60;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2195,7 +2202,7 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(EmojiParagraph)) {
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.font_family = "Noto Color Emoji";
|
||||
text_style.font_families = std::vector<std::string>(1, "Noto Color Emoji");
|
||||
text_style.font_size = 50;
|
||||
text_style.decoration = TextDecoration::kUnderline;
|
||||
builder.PushStyle(text_style);
|
||||
@ -2239,7 +2246,7 @@ TEST_F(ParagraphTest, HyphenBreakParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 31;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2283,7 +2290,7 @@ TEST_F(ParagraphTest, RepeatLayoutParagraph) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.font_size = 31;
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.word_spacing = 0;
|
||||
@ -2343,7 +2350,7 @@ TEST_F(ParagraphTest, Ellipsize) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
builder.AddText(u16_text);
|
||||
@ -2385,14 +2392,14 @@ TEST_F(ParagraphTest, UnderlineShiftParagraph) {
|
||||
|
||||
txt::TextStyle text_style1;
|
||||
text_style1.color = SK_ColorBLACK;
|
||||
text_style1.font_family = "Roboto";
|
||||
text_style1.font_families = std::vector<std::string>(1, "Roboto");
|
||||
builder.PushStyle(text_style1);
|
||||
|
||||
builder.AddText(u16_text1);
|
||||
|
||||
txt::TextStyle text_style2;
|
||||
text_style2.color = SK_ColorBLACK;
|
||||
text_style2.font_family = "Roboto";
|
||||
text_style2.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style2.decoration = TextDecoration::kUnderline;
|
||||
text_style2.decoration_color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style2);
|
||||
@ -2454,7 +2461,7 @@ TEST_F(ParagraphTest, SimpleShadow) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0),
|
||||
1.0);
|
||||
@ -2493,7 +2500,7 @@ TEST_F(ParagraphTest, ComplexShadow) {
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_family = "Roboto";
|
||||
text_style.font_families = std::vector<std::string>(1, "Roboto");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.text_shadows.emplace_back(SK_ColorBLACK, SkPoint::Make(2.0, 2.0),
|
||||
1.0);
|
||||
@ -2571,7 +2578,7 @@ TEST_F(ParagraphTest, BaselineParagraph) {
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.font_size = 55;
|
||||
text_style.letter_spacing = 2;
|
||||
text_style.font_family = "Source Han Serif CN";
|
||||
text_style.font_families = std::vector<std::string>(1, "Source Han Serif CN");
|
||||
text_style.decoration_style = txt::TextDecorationStyle::kSolid;
|
||||
text_style.decoration_color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
@ -2605,4 +2612,95 @@ TEST_F(ParagraphTest, BaselineParagraph) {
|
||||
ASSERT_TRUE(Snapshot());
|
||||
}
|
||||
|
||||
TEST_F(ParagraphTest, FontFallbackParagraph) {
|
||||
const char* text = "Roboto 字典 ";
|
||||
auto icu_text = icu::UnicodeString::fromUTF8(text);
|
||||
std::u16string u16_text(icu_text.getBuffer(),
|
||||
icu_text.getBuffer() + icu_text.length());
|
||||
const char* text2 = "Homemade Apple 字典";
|
||||
icu_text = icu::UnicodeString::fromUTF8(text2);
|
||||
std::u16string u16_text2(icu_text.getBuffer(),
|
||||
icu_text.getBuffer() + icu_text.length());
|
||||
const char* text3 = "Chinese 字典";
|
||||
icu_text = icu::UnicodeString::fromUTF8(text3);
|
||||
std::u16string u16_text3(icu_text.getBuffer(),
|
||||
icu_text.getBuffer() + icu_text.length());
|
||||
|
||||
txt::ParagraphStyle paragraph_style;
|
||||
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());
|
||||
|
||||
txt::TextStyle text_style;
|
||||
// No chinese fallback provided, should not be able to render the chinese.
|
||||
text_style.font_families = std::vector<std::string>(1, "Not a real font");
|
||||
text_style.font_families.push_back("Also a fake font");
|
||||
text_style.font_families.push_back("So fake it is obvious");
|
||||
text_style.font_families.push_back("Next one should be a real font...");
|
||||
text_style.font_families.push_back("Roboto");
|
||||
text_style.font_families.push_back("another fake one in between");
|
||||
text_style.font_families.push_back("Homemade Apple");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
builder.AddText(u16_text);
|
||||
|
||||
// Japanese version of the chinese should be rendered.
|
||||
text_style.font_families = std::vector<std::string>(1, "Not a real font");
|
||||
text_style.font_families.push_back("Also a fake font");
|
||||
text_style.font_families.push_back("So fake it is obvious");
|
||||
text_style.font_families.push_back("Homemade Apple");
|
||||
text_style.font_families.push_back("Next one should be a real font...");
|
||||
text_style.font_families.push_back("Roboto");
|
||||
text_style.font_families.push_back("another fake one in between");
|
||||
text_style.font_families.push_back("Noto Sans CJK JP");
|
||||
text_style.font_families.push_back("Source Han Serif CN");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
builder.AddText(u16_text2);
|
||||
|
||||
// Chinese font defiend first
|
||||
text_style.font_families = std::vector<std::string>(1, "Not a real font");
|
||||
text_style.font_families.push_back("Also a fake font");
|
||||
text_style.font_families.push_back("So fake it is obvious");
|
||||
text_style.font_families.push_back("Homemade Apple");
|
||||
text_style.font_families.push_back("Next one should be a real font...");
|
||||
text_style.font_families.push_back("Roboto");
|
||||
text_style.font_families.push_back("another fake one in between");
|
||||
text_style.font_families.push_back("Source Han Serif CN");
|
||||
text_style.font_families.push_back("Noto Sans CJK JP");
|
||||
text_style.color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
builder.AddText(u16_text3);
|
||||
|
||||
builder.Pop();
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 10.0, 15.0);
|
||||
|
||||
ASSERT_TRUE(Snapshot());
|
||||
|
||||
ASSERT_EQ(paragraph->records_.size(), 5ull);
|
||||
ASSERT_DOUBLE_EQ(paragraph->records_[0].GetRunWidth(), 64.19921875);
|
||||
ASSERT_DOUBLE_EQ(paragraph->records_[1].GetRunWidth(), 167.1171875);
|
||||
ASSERT_DOUBLE_EQ(paragraph->records_[2].GetRunWidth(), 167.1171875);
|
||||
ASSERT_DOUBLE_EQ(paragraph->records_[3].GetRunWidth(), 90.24609375);
|
||||
ASSERT_DOUBLE_EQ(paragraph->records_[4].GetRunWidth(), 90.24609375);
|
||||
// When a different font is resolved, then the metrics are different.
|
||||
ASSERT_TRUE(paragraph->records_[2].metrics().fTop -
|
||||
paragraph->records_[4].metrics().fTop !=
|
||||
0);
|
||||
ASSERT_TRUE(paragraph->records_[2].metrics().fAscent -
|
||||
paragraph->records_[4].metrics().fAscent !=
|
||||
0);
|
||||
ASSERT_TRUE(paragraph->records_[2].metrics().fDescent -
|
||||
paragraph->records_[4].metrics().fDescent !=
|
||||
0);
|
||||
ASSERT_TRUE(paragraph->records_[2].metrics().fBottom -
|
||||
paragraph->records_[4].metrics().fBottom !=
|
||||
0);
|
||||
ASSERT_TRUE(paragraph->records_[2].metrics().fAvgCharWidth -
|
||||
paragraph->records_[4].metrics().fAvgCharWidth !=
|
||||
0);
|
||||
}
|
||||
|
||||
} // namespace txt
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user