Skip to content

Commit b3387dc

Browse files
committed
Bug 1872545 - Hoist color-font palette cache out of TextRunDrawParams to the nsPresContext or CanvasRenderingContext2D, for greater effectiveness. r=gfx-reviewers,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D197463
1 parent 4f6c32c commit b3387dc

15 files changed

+161
-82
lines changed

dom/canvas/CanvasRenderingContext2D.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4251,7 +4251,8 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
42514251
: public nsBidiPresUtils::BidiProcessor {
42524252
using Style = CanvasRenderingContext2D::Style;
42534253

4254-
CanvasBidiProcessor() : nsBidiPresUtils::BidiProcessor() {
4254+
explicit CanvasBidiProcessor(mozilla::gfx::PaletteCache& aPaletteCache)
4255+
: mPaletteCache(aPaletteCache) {
42554256
if (StaticPrefs::gfx_missing_fonts_notify()) {
42564257
mMissingFonts = MakeUnique<gfxMissingFontRecorder>();
42574258
}
@@ -4496,7 +4497,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
44964497
}
44974498

44984499
gfxContext thebes(target, /* aPreserveTransform */ true);
4499-
gfxTextRun::DrawParams params(&thebes);
4500+
gfxTextRun::DrawParams params(&thebes, mPaletteCache);
45004501

45014502
params.allowGDI = false;
45024503

@@ -4566,6 +4567,9 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
45664567
// current font
45674568
gfxFontGroup* mFontgrp = nullptr;
45684569

4570+
// palette cache for COLR font rendering
4571+
mozilla::gfx::PaletteCache& mPaletteCache;
4572+
45694573
// spacing adjustments to be applied
45704574
gfx::Float mLetterSpacing = 0.0f;
45714575
gfx::Float mWordSpacing = 0.0f;
@@ -4687,7 +4691,7 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText(
46874691
return nullptr;
46884692
}
46894693

4690-
CanvasBidiProcessor processor;
4694+
CanvasBidiProcessor processor(mPaletteCache);
46914695

46924696
// If we don't have a ComputedStyle, we can't set up vertical-text flags
46934697
// (for now, at least; perhaps we need new Canvas API to control this).

dom/canvas/CanvasRenderingContext2D.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,8 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
11191119

11201120
ColorStyleCacheEntry ParseColorSlow(const nsACString&);
11211121

1122+
mozilla::gfx::PaletteCache mPaletteCache;
1123+
11221124
friend class CanvasGeneralPattern;
11231125
friend class AdjustedTarget;
11241126
friend class AdjustedTargetForShadow;

gfx/src/nsFontMetrics.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ void nsFontMetrics::DrawString(const char* aString, uint32_t aLength,
334334
pt.x += textRun->GetAdvanceWidth(range, &provider);
335335
}
336336
}
337-
gfxTextRun::DrawParams params(aContext);
337+
mozilla::gfx::PaletteCache paletteCache;
338+
gfxTextRun::DrawParams params(aContext, paletteCache);
338339
params.provider = &provider;
339340
textRun->Draw(range, pt, params);
340341
}
@@ -359,7 +360,8 @@ void nsFontMetrics::DrawString(
359360
pt.x += textRun->GetAdvanceWidth(range, &provider);
360361
}
361362
}
362-
gfxTextRun::DrawParams params(aContext);
363+
mozilla::gfx::PaletteCache paletteCache;
364+
gfxTextRun::DrawParams params(aContext, paletteCache);
363365
params.provider = &provider;
364366
textRun->Draw(range, pt, params);
365367
}

gfx/thebes/FontPaletteCache.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5+
6+
#include "FontPaletteCache.h"
7+
#include "COLRFonts.h"
8+
9+
void mozilla::gfx::PaletteCache::SetPaletteValueSet(
10+
const gfx::FontPaletteValueSet* aSet) {
11+
mPaletteValueSet = aSet;
12+
Clear();
13+
}
14+
15+
nsTArray<gfx::sRGBColor>* mozilla::gfx::PaletteCache::GetPaletteFor(
16+
gfxFontEntry* aFontEntry, nsAtom* aPaletteName) {
17+
auto entry = Lookup(std::pair(aFontEntry, aPaletteName));
18+
if (!entry) {
19+
CacheData newData;
20+
newData.mKey = std::pair(aFontEntry, aPaletteName);
21+
22+
gfxFontEntry::AutoHBFace face = aFontEntry->GetHBFace();
23+
newData.mPalette = gfx::COLRFonts::SetupColorPalette(
24+
face, mPaletteValueSet, aPaletteName, aFontEntry->FamilyName());
25+
26+
entry.Set(std::move(newData));
27+
}
28+
return entry.Data().mPalette.get();
29+
}

gfx/thebes/FontPaletteCache.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5+
6+
#ifndef FONT_PALETTE_CACHE_H
7+
#define FONT_PALETTE_CACHE_H
8+
9+
#include "gfxFontEntry.h"
10+
#include "mozilla/gfx/Types.h"
11+
#include "mozilla/MruCache.h"
12+
#include "mozilla/HashFunctions.h"
13+
#include "nsAtom.h"
14+
#include <utility>
15+
16+
namespace mozilla::gfx {
17+
18+
class FontPaletteValueSet;
19+
20+
// MRU cache used for resolved color-font palettes, to avoid reconstructing
21+
// the palette for each glyph rendered with a given font.
22+
using CacheKey = std::pair<RefPtr<gfxFontEntry>, RefPtr<nsAtom>>;
23+
struct CacheData {
24+
CacheKey mKey;
25+
mozilla::UniquePtr<nsTArray<mozilla::gfx::sRGBColor>> mPalette;
26+
};
27+
28+
class PaletteCache
29+
: public mozilla::MruCache<CacheKey, CacheData, PaletteCache> {
30+
public:
31+
explicit PaletteCache(const FontPaletteValueSet* aPaletteValueSet = nullptr)
32+
: mPaletteValueSet(aPaletteValueSet) {}
33+
34+
void SetPaletteValueSet(const FontPaletteValueSet* aSet);
35+
36+
nsTArray<mozilla::gfx::sRGBColor>* GetPaletteFor(gfxFontEntry* aFontEntry,
37+
nsAtom* aPaletteName);
38+
39+
static mozilla::HashNumber Hash(const CacheKey& aKey) {
40+
return mozilla::HashGeneric(aKey.first.get(), aKey.second.get());
41+
}
42+
static bool Match(const CacheKey& aKey, const CacheData& aVal) {
43+
return aVal.mKey == aKey;
44+
}
45+
46+
protected:
47+
const FontPaletteValueSet* mPaletteValueSet = nullptr;
48+
};
49+
50+
} // namespace mozilla::gfx
51+
52+
#endif

gfx/thebes/gfxFont.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,7 +1715,8 @@ bool gfxFont::HasFeatureSet(uint32_t aFeature, bool& aFeatureOn) {
17151715

17161716
already_AddRefed<mozilla::gfx::ScaledFont> gfxFont::GetScaledFont(
17171717
mozilla::gfx::DrawTarget* aDrawTarget) {
1718-
TextRunDrawParams params;
1718+
mozilla::gfx::PaletteCache dummy;
1719+
TextRunDrawParams params(dummy);
17191720
return GetScaledFont(params);
17201721
}
17211722

@@ -2233,7 +2234,7 @@ void gfxFont::DrawEmphasisMarks(const gfxTextRun* aShapedText, gfx::Point* aPt,
22332234
const EmphasisMarkDrawParams& aParams) {
22342235
float& inlineCoord = aParams.isVertical ? aPt->y.value : aPt->x.value;
22352236
gfxTextRun::Range markRange(aParams.mark);
2236-
gfxTextRun::DrawParams params(aParams.context);
2237+
gfxTextRun::DrawParams params(aParams.context, aParams.paletteCache);
22372238

22382239
float clusterStart = -std::numeric_limits<float>::infinity();
22392240
bool shouldDrawEmphasisMark = false;
@@ -2265,23 +2266,6 @@ void gfxFont::DrawEmphasisMarks(const gfxTextRun* aShapedText, gfx::Point* aPt,
22652266
}
22662267
}
22672268

2268-
nsTArray<mozilla::gfx::sRGBColor>* TextRunDrawParams::GetPaletteFor(
2269-
const gfxFont* aFont) {
2270-
auto entry = mPaletteCache.Lookup(aFont);
2271-
if (!entry) {
2272-
CacheData newData;
2273-
newData.mKey = aFont;
2274-
2275-
gfxFontEntry* fe = aFont->GetFontEntry();
2276-
gfxFontEntry::AutoHBFace face = fe->GetHBFace();
2277-
newData.mPalette = COLRFonts::SetupColorPalette(
2278-
face, paletteValueSet, fontPalette, fe->FamilyName());
2279-
2280-
entry.Set(std::move(newData));
2281-
}
2282-
return entry.Data().mPalette.get();
2283-
}
2284-
22852269
void gfxFont::Draw(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
22862270
gfx::Point* aPt, TextRunDrawParams& aRunParams,
22872271
gfx::ShapedTextFlags aOrientation) {
@@ -2317,7 +2301,8 @@ void gfxFont::Draw(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd,
23172301
fontParams.currentColor = aRunParams.context->GetDeviceColor(ctxColor)
23182302
? sRGBColor::FromABGR(ctxColor.ToABGR())
23192303
: sRGBColor::OpaqueBlack();
2320-
fontParams.palette = aRunParams.GetPaletteFor(this);
2304+
fontParams.palette = aRunParams.paletteCache.GetPaletteFor(
2305+
GetFontEntry(), aRunParams.fontPalette);
23212306
}
23222307

23232308
if (textDrawer) {

gfx/thebes/gfxFont.h

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <new>
1111
#include <utility>
1212
#include <functional>
13+
#include "FontPaletteCache.h"
1314
#include "PLDHashTable.h"
1415
#include "ThebesRLBoxTypes.h"
1516
#include "gfxFontVariations.h"
@@ -2299,6 +2300,10 @@ class gfxFont {
22992300
// are dependent on the specific font, so they are set per GlyphRun.
23002301
23012302
struct MOZ_STACK_CLASS TextRunDrawParams {
2303+
explicit TextRunDrawParams(mozilla::gfx::PaletteCache& aPaletteCache)
2304+
: paletteCache(aPaletteCache) {}
2305+
2306+
mozilla::gfx::PaletteCache& paletteCache;
23022307
RefPtr<mozilla::gfx::DrawTarget> dt;
23032308
gfxContext* context = nullptr;
23042309
gfxFont::Spacing* spacing = nullptr;
@@ -2312,42 +2317,13 @@ struct MOZ_STACK_CLASS TextRunDrawParams {
23122317
gfxPattern* textStrokePattern = nullptr;
23132318
const mozilla::gfx::StrokeOptions* strokeOpts = nullptr;
23142319
const mozilla::gfx::DrawOptions* drawOpts = nullptr;
2315-
const mozilla::gfx::FontPaletteValueSet* paletteValueSet = nullptr;
23162320
nsAtom* fontPalette = nullptr;
23172321
DrawMode drawMode = DrawMode::GLYPH_FILL;
23182322
bool isVerticalRun = false;
23192323
bool isRTL = false;
23202324
bool paintSVGGlyphs = true;
23212325
bool allowGDI = true;
23222326
bool hasTextShadow = false;
2323-
2324-
// MRU cache of color-font palettes being used by fonts in the run. We cache
2325-
// these in the TextRunDrawParams so that we can avoid re-creating a new
2326-
// palette (which can be quite expensive) for each individual glyph run.
2327-
using CacheKey = const gfxFont*;
2328-
2329-
struct CacheData {
2330-
CacheKey mKey;
2331-
mozilla::UniquePtr<nsTArray<mozilla::gfx::sRGBColor>> mPalette;
2332-
};
2333-
2334-
class PaletteCache
2335-
: public mozilla::MruCache<CacheKey, CacheData, PaletteCache> {
2336-
public:
2337-
static mozilla::HashNumber Hash(const CacheKey& aKey) {
2338-
return mozilla::HashGeneric(aKey);
2339-
}
2340-
static bool Match(const CacheKey& aKey, const CacheData& aVal) {
2341-
return aVal.mKey == aKey;
2342-
}
2343-
};
2344-
2345-
PaletteCache mPaletteCache;
2346-
2347-
// Returns a pointer to a palette owned by the PaletteCache. This is only
2348-
// valid until the next call to GetPaletteFor (which might evict it) or
2349-
// until the TextRunDrawParams goes out of scope.
2350-
nsTArray<mozilla::gfx::sRGBColor>* GetPaletteFor(const gfxFont* aFont);
23512327
};
23522328
23532329
struct MOZ_STACK_CLASS FontDrawParams {
@@ -2368,7 +2344,11 @@ struct MOZ_STACK_CLASS FontDrawParams {
23682344
};
23692345
23702346
struct MOZ_STACK_CLASS EmphasisMarkDrawParams {
2347+
EmphasisMarkDrawParams(gfxContext* aContext,
2348+
mozilla::gfx::PaletteCache& aPaletteCache)
2349+
: context(aContext), paletteCache(aPaletteCache) {}
23712350
gfxContext* context;
2351+
mozilla::gfx::PaletteCache& paletteCache;
23722352
gfxFont::Spacing* spacing;
23732353
gfxTextRun* mark;
23742354
gfxFloat advance;

gfx/thebes/gfxTextRun.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt,
611611

612612
// Set up parameters that will be constant across all glyph runs we need
613613
// to draw, regardless of the font used.
614-
TextRunDrawParams params;
614+
TextRunDrawParams params(aParams.paletteCache);
615615
params.context = aParams.context;
616616
params.devPerApp = 1.0 / double(GetAppUnitsPerDevUnit());
617617
params.isVerticalRun = IsVertical();
@@ -620,7 +620,6 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt,
620620
params.strokeOpts = aParams.strokeOpts;
621621
params.textStrokeColor = aParams.textStrokeColor;
622622
params.fontPalette = aParams.fontPalette;
623-
params.paletteValueSet = aParams.paletteValueSet;
624623
params.textStrokePattern = aParams.textStrokePattern;
625624
params.drawOpts = aParams.drawOpts;
626625
params.drawMode = aParams.drawMode;
@@ -710,14 +709,13 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt,
710709
}
711710

712711
// This method is mostly parallel to Draw().
713-
void gfxTextRun::DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
714-
gfxFloat aMarkAdvance, gfx::Point aPt,
715-
Range aRange,
716-
const PropertyProvider* aProvider) const {
712+
void gfxTextRun::DrawEmphasisMarks(
713+
gfxContext* aContext, gfxTextRun* aMark, gfxFloat aMarkAdvance,
714+
gfx::Point aPt, Range aRange, const PropertyProvider* aProvider,
715+
mozilla::gfx::PaletteCache& aPaletteCache) const {
717716
MOZ_ASSERT(aRange.end <= GetLength());
718717

719-
EmphasisMarkDrawParams params;
720-
params.context = aContext;
718+
EmphasisMarkDrawParams params(aContext, aPaletteCache);
721719
params.mark = aMark;
722720
params.advance = aMarkAdvance;
723721
params.direction = GetDirection();

gfx/thebes/gfxTextRun.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,10 @@ class gfxTextRun : public gfxShapedText {
251251

252252
struct MOZ_STACK_CLASS DrawParams {
253253
gfxContext* context;
254+
mozilla::gfx::PaletteCache& paletteCache;
254255
DrawMode drawMode = DrawMode::GLYPH_FILL;
255256
nscolor textStrokeColor = 0;
256257
nsAtom* fontPalette = nullptr;
257-
mozilla::gfx::FontPaletteValueSet* paletteValueSet = nullptr;
258258
gfxPattern* textStrokePattern = nullptr;
259259
const mozilla::gfx::StrokeOptions* strokeOpts = nullptr;
260260
const mozilla::gfx::DrawOptions* drawOpts = nullptr;
@@ -265,7 +265,8 @@ class gfxTextRun : public gfxShapedText {
265265
gfxTextRunDrawCallbacks* callbacks = nullptr;
266266
bool allowGDI = true;
267267
bool hasTextShadow = false;
268-
explicit DrawParams(gfxContext* aContext) : context(aContext) {}
268+
DrawParams(gfxContext* aContext, mozilla::gfx::PaletteCache& aPaletteCache)
269+
: context(aContext), paletteCache(aPaletteCache) {}
269270
};
270271

271272
/**
@@ -298,7 +299,8 @@ class gfxTextRun : public gfxShapedText {
298299
*/
299300
void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
300301
gfxFloat aMarkAdvance, mozilla::gfx::Point aPt,
301-
Range aRange, const PropertyProvider* aProvider) const;
302+
Range aRange, const PropertyProvider* aProvider,
303+
mozilla::gfx::PaletteCache& aPaletteCache) const;
302304

303305
/**
304306
* Computes the ReflowMetrics for a substring.

gfx/thebes/moz.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ XPIDL_MODULE = "gfx"
1919
EXPORTS += [
2020
"COLRFonts.h",
2121
"DrawMode.h",
22+
"FontPaletteCache.h",
2223
"gfx2DGlue.h",
2324
"gfxAlphaRecovery.h",
2425
"gfxASurface.h",
@@ -198,6 +199,7 @@ SOURCES += [
198199
UNIFIED_SOURCES += [
199200
"CJKCompatSVS.cpp",
200201
"COLRFonts.cpp",
202+
"FontPaletteCache.cpp",
201203
"gfxAlphaRecovery.cpp",
202204
"gfxBaseSharedMemorySurface.cpp",
203205
"gfxBlur.cpp",

0 commit comments

Comments
 (0)