Bug 1699835 - Check that references in cached fontGroup match current presContext. r=lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D109612
This commit is contained in:
Jonathan Kew 2021-03-30 16:02:24 +00:00
parent 91dfab0b43
commit 5d763da0ba
3 changed files with 38 additions and 17 deletions

View File

@ -4040,13 +4040,37 @@ TextMetrics* CanvasRenderingContext2D::DrawOrMeasureText(
}
gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
// use lazy initilization for the font group since it's rather expensive
if (!CurrentState().fontGroup) {
// Use lazy (re)initialization for the fontGroup since it's rather expensive.
RefPtr<PresShell> presShell = GetPresShell();
gfxTextPerfMetrics* tp = nullptr;
FontMatchingStats* fontStats = nullptr;
if (presShell && !presShell->IsDestroying()) {
nsPresContext* pc = presShell->GetPresContext();
tp = pc->GetTextPerfMetrics();
fontStats = pc->GetFontMatchingStats();
}
// If we have a cached fontGroup, check that it is valid for the current
// prescontext; if not, we need to discard and re-create it.
RefPtr<gfxFontGroup>& fontGroup = CurrentState().fontGroup;
if (fontGroup) {
if (fontGroup->GetFontMatchingStats() != fontStats ||
fontGroup->GetTextPerfMetrics() != tp) {
fontGroup = nullptr;
}
}
if (!fontGroup) {
ErrorResult err;
constexpr auto kDefaultFontStyle = "10px sans-serif"_ns;
static float kDefaultFontSize = 10.0;
RefPtr<PresShell> presShell = GetPresShell();
bool fontUpdated = SetFontInternal(kDefaultFontStyle, err);
const float kDefaultFontSize = 10.0;
// If the font has already been set, we're re-creating the fontGroup
// and should re-use the existing font attribute; if not, we initialize
// it to the canvas default.
const nsCString& currentFont = CurrentState().font;
bool fontUpdated = SetFontInternal(
currentFont.IsEmpty() ? kDefaultFontStyle : currentFont, err);
if (err.Failed() || !fontUpdated) {
err.SuppressException();
// XXX Should we get a default lang from the prescontext or something?
@ -4054,19 +4078,13 @@ gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
bool explicitLanguage = false;
gfxFontStyle style;
style.size = kDefaultFontSize;
gfxTextPerfMetrics* tp = nullptr;
FontMatchingStats* fontStats = nullptr;
if (presShell && !presShell->IsDestroying()) {
tp = presShell->GetPresContext()->GetTextPerfMetrics();
fontStats = presShell->GetPresContext()->GetFontMatchingStats();
}
int32_t perDevPixel, perCSSPixel;
GetAppUnitsValues(&perDevPixel, &perCSSPixel);
gfxFloat devToCssSize = gfxFloat(perDevPixel) / gfxFloat(perCSSPixel);
CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(
FontFamilyList(StyleGenericFontFamily::SansSerif), &style, language,
explicitLanguage, tp, fontStats, nullptr, devToCssSize);
if (CurrentState().fontGroup) {
if (fontGroup) {
CurrentState().font = kDefaultFontStyle;
} else {
NS_ERROR("Default canvas font is invalid");
@ -4074,10 +4092,10 @@ gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
}
} else {
// The fontgroup needs to check if its cached families/faces are valid.
CurrentState().fontGroup->CheckForUpdatedPlatformList();
fontGroup->CheckForUpdatedPlatformList();
}
return CurrentState().fontGroup;
return fontGroup;
}
//

View File

@ -150,7 +150,8 @@ already_AddRefed<nsFontMetrics> nsFontCache::GetMetricsFor(
fm->GetUserFontSet() == aParams.userFontSet &&
fm->Language() == language &&
fm->Orientation() == aParams.orientation &&
fm->ExplicitLanguage() == aParams.explicitLanguage) {
fm->ExplicitLanguage() == aParams.explicitLanguage &&
fm->GetThebesFontGroup()->GetFontMatchingStats() == aParams.fontStats) {
if (i != n) {
// promote it to the end of the cache
mFontMetrics.RemoveElementAt(i);

View File

@ -1049,7 +1049,9 @@ class gfxFontGroup final : public gfxTextRunFactory {
uint64_t GetRebuildGeneration();
// used when logging text performance
gfxTextPerfMetrics* GetTextPerfMetrics() { return mTextPerf; }
gfxTextPerfMetrics* GetTextPerfMetrics() const { return mTextPerf; }
FontMatchingStats* GetFontMatchingStats() const { return mFontMatchingStats; }
// This will call UpdateUserFonts() if the user font set is changed.
void SetUserFontSet(gfxUserFontSet* aUserFontSet);