зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1714282 - Handle bitmap font sizes in the shared font list on Linux. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D116874
This commit is contained in:
Родитель
72f885fa29
Коммит
2f1aa020c3
|
@ -11,6 +11,7 @@
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
|
|
||||||
#define LOG_FONTLIST(args) \
|
#define LOG_FONTLIST(args) \
|
||||||
MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), LogLevel::Debug, args)
|
MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), LogLevel::Debug, args)
|
||||||
|
@ -231,34 +232,46 @@ void Family::AddFaces(FontList* aList, const nsTArray<Face::InitData>& aFaces) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
bool Family::FindAllFacesForStyleInternal(FontList* aList,
|
||||||
nsTArray<Face*>& aFaceList,
|
const gfxFontStyle& aStyle,
|
||||||
bool aIgnoreSizeTolerance) const {
|
nsTArray<Face*>& aFaceList) const {
|
||||||
MOZ_ASSERT(aFaceList.IsEmpty());
|
MOZ_ASSERT(aFaceList.IsEmpty());
|
||||||
if (!IsInitialized()) {
|
if (!IsInitialized()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer* facePtrs = Faces(aList);
|
Pointer* facePtrs = Faces(aList);
|
||||||
if (!facePtrs) {
|
if (!facePtrs) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the family has only one face, we simply return it; no further
|
// Depending on the kind of family, we have to do varying amounts of work
|
||||||
// checking needed.
|
// to figure out what face(s) to use for the requested style properties.
|
||||||
|
|
||||||
|
// If the family has only one face, we simply use it; no further style
|
||||||
|
// checking needed. (However, for bitmap fonts we may still need to check
|
||||||
|
// whether the size is acceptable.)
|
||||||
if (NumFaces() == 1) {
|
if (NumFaces() == 1) {
|
||||||
MOZ_ASSERT(!facePtrs[0].IsNull());
|
MOZ_ASSERT(!facePtrs[0].IsNull());
|
||||||
aFaceList.AppendElement(static_cast<Face*>(facePtrs[0].ToPtr(aList)));
|
Face* face = static_cast<Face*>(facePtrs[0].ToPtr(aList));
|
||||||
return;
|
if (face && face->HasValidDescriptor()) {
|
||||||
|
aFaceList.AppendElement(face);
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (face->mSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most families are "simple", having just Regular/Bold/Italic/BoldItalic,
|
// Most families are "simple", having just Regular/Bold/Italic/BoldItalic,
|
||||||
// or some subset of these. In this case, we have exactly 4 entries in
|
// or some subset of these. In this case, we have exactly 4 entries in
|
||||||
// mAvailableFonts, stored in the above order; note that some of the entries
|
// mAvailableFonts, stored in the above order; note that some of the entries
|
||||||
// may be nullptr. We can then pick the required entry based on whether the
|
// may be nullptr. We can then pick the required entry based on whether the
|
||||||
// request is for bold or non-bold, italic or non-italic, without running the
|
// request is for bold or non-bold, italic or non-italic, without running
|
||||||
// more complex matching algorithm used for larger families with many weights
|
// the more complex matching algorithm used for larger families with many
|
||||||
// and/or widths.
|
// weights and/or widths.
|
||||||
|
|
||||||
if (mIsSimple) {
|
if (mIsSimple) {
|
||||||
// Family has no more than the "standard" 4 faces, at fixed indexes;
|
// Family has no more than the "standard" 4 faces, at fixed indexes;
|
||||||
|
@ -270,15 +283,20 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
uint8_t faceIndex =
|
uint8_t faceIndex =
|
||||||
(wantItalic ? kItalicMask : 0) | (wantBold ? kBoldMask : 0);
|
(wantItalic ? kItalicMask : 0) | (wantBold ? kBoldMask : 0);
|
||||||
|
|
||||||
// if the desired style is available, return it directly
|
// If the desired style is available, use it directly.
|
||||||
Face* face = static_cast<Face*>(facePtrs[faceIndex].ToPtr(aList));
|
Face* face = static_cast<Face*>(facePtrs[faceIndex].ToPtr(aList));
|
||||||
if (face && face->HasValidDescriptor()) {
|
if (face && face->HasValidDescriptor()) {
|
||||||
aFaceList.AppendElement(face);
|
aFaceList.AppendElement(face);
|
||||||
return;
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (face->mSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// order to check fallback faces in a simple family, depending on requested
|
// Order to check fallback faces in a simple family, depending on the
|
||||||
// style
|
// requested style.
|
||||||
static const uint8_t simpleFallbacks[4][3] = {
|
static const uint8_t simpleFallbacks[4][3] = {
|
||||||
{kBoldFaceIndex, kItalicFaceIndex,
|
{kBoldFaceIndex, kItalicFaceIndex,
|
||||||
kBoldItalicFaceIndex}, // fallback sequence for Regular
|
kBoldItalicFaceIndex}, // fallback sequence for Regular
|
||||||
|
@ -294,7 +312,12 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
face = static_cast<Face*>(facePtrs[order[trial]].ToPtr(aList));
|
face = static_cast<Face*>(facePtrs[order[trial]].ToPtr(aList));
|
||||||
if (face && face->HasValidDescriptor()) {
|
if (face && face->HasValidDescriptor()) {
|
||||||
aFaceList.AppendElement(face);
|
aFaceList.AppendElement(face);
|
||||||
return;
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (face->mSize) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +325,7 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
// can happen if we're on a stylo thread and caught the font list being
|
// can happen if we're on a stylo thread and caught the font list being
|
||||||
// updated; in that case we just fail quietly and let font fallback do
|
// updated; in that case we just fail quietly and let font fallback do
|
||||||
// something for the time being.
|
// something for the time being.
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick the font(s) that are closest to the desired weight, style, and
|
// Pick the font(s) that are closest to the desired weight, style, and
|
||||||
|
@ -315,9 +338,11 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
// normal platform fonts with a single font entry for each
|
// normal platform fonts with a single font entry for each
|
||||||
// weight/style/stretch combination, only the last matched font entry will
|
// weight/style/stretch combination, only the last matched font entry will
|
||||||
// be added.
|
// be added.
|
||||||
|
|
||||||
double minDistance = INFINITY;
|
double minDistance = INFINITY;
|
||||||
Face* matched = nullptr;
|
Face* matched = nullptr;
|
||||||
|
// Keep track of whether we've included any non-scalable font resources in
|
||||||
|
// the selected set.
|
||||||
|
bool anyNonScalable = false;
|
||||||
for (uint32_t i = 0; i < NumFaces(); i++) {
|
for (uint32_t i = 0; i < NumFaces(); i++) {
|
||||||
Face* face = static_cast<Face*>(facePtrs[i].ToPtr(aList));
|
Face* face = static_cast<Face*>(facePtrs[i].ToPtr(aList));
|
||||||
if (face) {
|
if (face) {
|
||||||
|
@ -332,6 +357,11 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
} else if (distance == minDistance) {
|
} else if (distance == minDistance) {
|
||||||
if (matched) {
|
if (matched) {
|
||||||
aFaceList.AppendElement(matched);
|
aFaceList.AppendElement(matched);
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (matched->mSize) {
|
||||||
|
anyNonScalable = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
matched = face;
|
matched = face;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +371,69 @@ void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
MOZ_ASSERT(matched, "didn't match a font within a family");
|
MOZ_ASSERT(matched, "didn't match a font within a family");
|
||||||
if (matched) {
|
if (matched) {
|
||||||
aFaceList.AppendElement(matched);
|
aFaceList.AppendElement(matched);
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
if (matched->mSize) {
|
||||||
|
anyNonScalable = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyNonScalable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Family::FindAllFacesForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
|
nsTArray<Face*>& aFaceList,
|
||||||
|
bool aIgnoreSizeTolerance) const {
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
bool anyNonScalable =
|
||||||
|
#else
|
||||||
|
Unused <<
|
||||||
|
#endif
|
||||||
|
FindAllFacesForStyleInternal(aList, aStyle, aFaceList);
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
// aFaceList now contains whatever faces are the best style match for
|
||||||
|
// the requested style. If specifically-sized bitmap faces are supported,
|
||||||
|
// we need to additionally filter the list to choose the appropriate size.
|
||||||
|
//
|
||||||
|
// It would be slightly more efficient to integrate this directly into the
|
||||||
|
// face-selection algorithm above, but it's a rare case that doesn't apply
|
||||||
|
// at all to most font families.
|
||||||
|
//
|
||||||
|
// Currently we only support pixel-sized bitmap font faces on Linux/Gtk (i.e.
|
||||||
|
// when using the gfxFcPlatformFontList implementation), so this filtering is
|
||||||
|
// not needed on other platforms.
|
||||||
|
//
|
||||||
|
// (Note that color-bitmap emoji fonts like Apple Color Emoji or Noto Color
|
||||||
|
// Emoji don't count here; they package multiple bitmap sizes into a single
|
||||||
|
// OpenType wrapper, so they appear as a single "scalable" face in our list.)
|
||||||
|
if (anyNonScalable) {
|
||||||
|
uint16_t best = 0;
|
||||||
|
gfxFloat dist = 0.0;
|
||||||
|
for (const auto& f : aFaceList) {
|
||||||
|
if (f->mSize == 0) {
|
||||||
|
// Scalable face; no size distance to compute.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gfxFloat d = fabs(gfxFloat(f->mSize) - aStyle.size);
|
||||||
|
if (!aIgnoreSizeTolerance && (d * 5.0 > f->mSize)) {
|
||||||
|
continue; // Too far from the requested size, ignore.
|
||||||
|
}
|
||||||
|
// If we haven't found a "best" bitmap size yet, or if this is a better
|
||||||
|
// match, remember it.
|
||||||
|
if (!best || d < dist) {
|
||||||
|
best = f->mSize;
|
||||||
|
dist = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Discard all faces except the chosen "best" size; or if no pixel size was
|
||||||
|
// chosen, all except scalable faces.
|
||||||
|
// This may eliminate *all* faces in the family, if all were bitmaps and
|
||||||
|
// none was a good enough size match, in which case we'll fall back to the
|
||||||
|
// next font-family name.
|
||||||
|
aFaceList.RemoveElementsBy([=](const auto& e) { return e->mSize != best; });
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Face* Family::FindFaceForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
Face* Family::FindFaceForStyle(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
|
|
|
@ -157,6 +157,9 @@ struct Face {
|
||||||
nsCString mDescriptor; // descriptor that can be used to instantiate a
|
nsCString mDescriptor; // descriptor that can be used to instantiate a
|
||||||
// platform font reference
|
// platform font reference
|
||||||
uint16_t mIndex; // an index used with descriptor (on some platforms)
|
uint16_t mIndex; // an index used with descriptor (on some platforms)
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
uint16_t mSize; // pixel size if bitmap; zero indicates scalable
|
||||||
|
#endif
|
||||||
bool mFixedPitch; // is the face fixed-pitch (monospaced)?
|
bool mFixedPitch; // is the face fixed-pitch (monospaced)?
|
||||||
mozilla::WeightRange mWeight; // CSS font-weight value
|
mozilla::WeightRange mWeight; // CSS font-weight value
|
||||||
mozilla::StretchRange mStretch; // CSS font-stretch value
|
mozilla::StretchRange mStretch; // CSS font-stretch value
|
||||||
|
@ -169,11 +172,15 @@ struct Face {
|
||||||
Face(FontList* aList, const InitData& aData)
|
Face(FontList* aList, const InitData& aData)
|
||||||
: mDescriptor(aList, aData.mDescriptor),
|
: mDescriptor(aList, aData.mDescriptor),
|
||||||
mIndex(aData.mIndex),
|
mIndex(aData.mIndex),
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
mSize(aData.mSize),
|
||||||
|
#endif
|
||||||
mFixedPitch(aData.mFixedPitch),
|
mFixedPitch(aData.mFixedPitch),
|
||||||
mWeight(aData.mWeight),
|
mWeight(aData.mWeight),
|
||||||
mStretch(aData.mStretch),
|
mStretch(aData.mStretch),
|
||||||
mStyle(aData.mStyle),
|
mStyle(aData.mStyle),
|
||||||
mCharacterMap(Pointer::Null()) {}
|
mCharacterMap(Pointer::Null()) {
|
||||||
|
}
|
||||||
|
|
||||||
bool HasValidDescriptor() const {
|
bool HasValidDescriptor() const {
|
||||||
return !mDescriptor.IsNull() && mIndex != uint16_t(-1);
|
return !mDescriptor.IsNull() && mIndex != uint16_t(-1);
|
||||||
|
@ -183,6 +190,9 @@ struct Face {
|
||||||
|
|
||||||
String mDescriptor;
|
String mDescriptor;
|
||||||
uint16_t mIndex;
|
uint16_t mIndex;
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
uint16_t mSize;
|
||||||
|
#endif
|
||||||
bool mFixedPitch;
|
bool mFixedPitch;
|
||||||
mozilla::WeightRange mWeight;
|
mozilla::WeightRange mWeight;
|
||||||
mozilla::StretchRange mStretch;
|
mozilla::StretchRange mStretch;
|
||||||
|
@ -309,6 +319,11 @@ struct Family {
|
||||||
void SetupFamilyCharMap(FontList* aList);
|
void SetupFamilyCharMap(FontList* aList);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Returns true if there are specifically-sized bitmap faces in the list,
|
||||||
|
// so size selection still needs to be done. (Currently only on Linux.)
|
||||||
|
bool FindAllFacesForStyleInternal(FontList* aList, const gfxFontStyle& aStyle,
|
||||||
|
nsTArray<Face*>& aFaceList) const;
|
||||||
|
|
||||||
std::atomic<uint32_t> mFaceCount;
|
std::atomic<uint32_t> mFaceCount;
|
||||||
String mKey;
|
String mKey;
|
||||||
String mName;
|
String mName;
|
||||||
|
|
|
@ -205,7 +205,8 @@ static FontStretch MapFcWidth(int aFcWidth) {
|
||||||
|
|
||||||
static void GetFontProperties(FcPattern* aFontPattern, WeightRange* aWeight,
|
static void GetFontProperties(FcPattern* aFontPattern, WeightRange* aWeight,
|
||||||
StretchRange* aStretch,
|
StretchRange* aStretch,
|
||||||
SlantStyleRange* aSlantStyle) {
|
SlantStyleRange* aSlantStyle,
|
||||||
|
uint16_t* aSize = nullptr) {
|
||||||
// weight
|
// weight
|
||||||
int weight;
|
int weight;
|
||||||
if (FcPatternGetInteger(aFontPattern, FC_WEIGHT, 0, &weight) !=
|
if (FcPatternGetInteger(aFontPattern, FC_WEIGHT, 0, &weight) !=
|
||||||
|
@ -231,6 +232,24 @@ static void GetFontProperties(FcPattern* aFontPattern, WeightRange* aWeight,
|
||||||
} else if (slant > 0) {
|
} else if (slant > 0) {
|
||||||
*aSlantStyle = SlantStyleRange(FontSlantStyle::Italic());
|
*aSlantStyle = SlantStyleRange(FontSlantStyle::Italic());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aSize) {
|
||||||
|
// pixel size, or zero if scalable
|
||||||
|
FcBool scalable;
|
||||||
|
if (FcPatternGetBool(aFontPattern, FC_SCALABLE, 0, &scalable) ==
|
||||||
|
FcResultMatch &&
|
||||||
|
scalable) {
|
||||||
|
*aSize = 0;
|
||||||
|
} else {
|
||||||
|
double size;
|
||||||
|
if (FcPatternGetDouble(aFontPattern, FC_PIXEL_SIZE, 0, &size) ==
|
||||||
|
FcResultMatch) {
|
||||||
|
*aSize = uint16_t(NS_round(size));
|
||||||
|
} else {
|
||||||
|
*aSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||||
|
@ -1667,10 +1686,11 @@ void gfxFcPlatformFontList::InitSharedFontListForPlatform() {
|
||||||
WeightRange weight(FontWeight::Normal());
|
WeightRange weight(FontWeight::Normal());
|
||||||
StretchRange stretch(FontStretch::Normal());
|
StretchRange stretch(FontStretch::Normal());
|
||||||
SlantStyleRange style(FontSlantStyle::Normal());
|
SlantStyleRange style(FontSlantStyle::Normal());
|
||||||
GetFontProperties(aPattern, &weight, &stretch, &style);
|
uint16_t size;
|
||||||
|
GetFontProperties(aPattern, &weight, &stretch, &style, &size);
|
||||||
|
|
||||||
auto initData =
|
auto initData = fontlist::Face::InitData{descriptor, 0, size, false,
|
||||||
fontlist::Face::InitData{descriptor, 0, false, weight, stretch, style};
|
weight, stretch, style};
|
||||||
|
|
||||||
// Add entries for any other localized family names. (Most fonts only have
|
// Add entries for any other localized family names. (Most fonts only have
|
||||||
// a single family name, so the first call to GetString will usually fail).
|
// a single family name, so the first call to GetString will usually fail).
|
||||||
|
|
Загрузка…
Ссылка в новой задаче