mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1815396 - Add an MruCache for ParseColor, just like we have for fonts. r=gfx-reviewers,lsalzman
Since currentColor usage is expected to be ~0, don't make the restyle generation etc part of the cache. Differential Revision: https://phabricator.services.mozilla.com/D171654
This commit is contained in:
parent
58dfff38db
commit
588855a7db
@ -839,20 +839,20 @@ void CanvasGradient::AddColorStop(float aOffset, const nsACString& aColorstr,
|
||||
return aRv.ThrowIndexSizeError("Offset out of 0-1.0 range");
|
||||
}
|
||||
|
||||
PresShell* presShell = mContext ? mContext->GetPresShell() : nullptr;
|
||||
ServoStyleSet* styleSet = presShell ? presShell->StyleSet() : nullptr;
|
||||
if (!mContext) {
|
||||
return aRv.ThrowSyntaxError("No canvas context");
|
||||
}
|
||||
|
||||
nscolor color;
|
||||
bool ok = ServoCSSParser::ComputeColor(styleSet, NS_RGB(0, 0, 0), aColorstr,
|
||||
&color);
|
||||
if (!ok) {
|
||||
auto color = mContext->ParseColor(
|
||||
aColorstr, CanvasRenderingContext2D::ResolveCurrentColor::No);
|
||||
if (!color) {
|
||||
return aRv.ThrowSyntaxError("Invalid color");
|
||||
}
|
||||
|
||||
GradientStop newStop;
|
||||
|
||||
newStop.offset = aOffset;
|
||||
newStop.color = ToDeviceColor(color);
|
||||
newStop.color = ToDeviceColor(*color);
|
||||
|
||||
mRawStops.AppendElement(newStop);
|
||||
}
|
||||
@ -1083,32 +1083,44 @@ JSObject* CanvasRenderingContext2D::WrapObject(
|
||||
return CanvasRenderingContext2D_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
bool CanvasRenderingContext2D::ParseColor(const nsACString& aString,
|
||||
nscolor* aColor) {
|
||||
CanvasRenderingContext2D::ColorStyleCacheEntry
|
||||
CanvasRenderingContext2D::ParseColorSlow(const nsACString& aString) {
|
||||
ColorStyleCacheEntry result{nsCString(aString)};
|
||||
Document* document = mCanvasElement ? mCanvasElement->OwnerDoc() : nullptr;
|
||||
css::Loader* loader = document ? document->CSSLoader() : nullptr;
|
||||
|
||||
PresShell* presShell = GetPresShell();
|
||||
ServoStyleSet* set = presShell ? presShell->StyleSet() : nullptr;
|
||||
|
||||
// First, try computing the color without handling currentcolor.
|
||||
bool wasCurrentColor = false;
|
||||
if (!ServoCSSParser::ComputeColor(set, NS_RGB(0, 0, 0), aString, aColor,
|
||||
&wasCurrentColor, loader)) {
|
||||
return false;
|
||||
nscolor color;
|
||||
if (ServoCSSParser::ComputeColor(set, NS_RGB(0, 0, 0), aString, &color,
|
||||
&wasCurrentColor, loader)) {
|
||||
result.mWasCurrentColor = wasCurrentColor;
|
||||
result.mColor.emplace(color);
|
||||
}
|
||||
|
||||
if (wasCurrentColor && mCanvasElement) {
|
||||
// Otherwise, get the value of the color property, flushing style
|
||||
// if necessary.
|
||||
return result;
|
||||
}
|
||||
|
||||
Maybe<nscolor> CanvasRenderingContext2D::ParseColor(
|
||||
const nsACString& aString, ResolveCurrentColor aResolveCurrentColor) {
|
||||
auto entry = mColorStyleCache.Lookup(aString);
|
||||
if (!entry) {
|
||||
entry.Set(ParseColorSlow(aString));
|
||||
}
|
||||
|
||||
const auto& data = entry.Data();
|
||||
if (data.mWasCurrentColor && mCanvasElement &&
|
||||
aResolveCurrentColor == ResolveCurrentColor::Yes) {
|
||||
// If it was currentColor, get the value of the color property, flushing
|
||||
// style if necessary.
|
||||
RefPtr<const ComputedStyle> canvasStyle =
|
||||
nsComputedDOMStyle::GetComputedStyle(mCanvasElement);
|
||||
if (canvasStyle) {
|
||||
*aColor = canvasStyle->StyleText()->mColor.ToColor();
|
||||
return Some(canvasStyle->StyleText()->mColor.ToColor());
|
||||
}
|
||||
// Beware that the presShell could be gone here.
|
||||
}
|
||||
return true;
|
||||
return data.mColor;
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::ResetBitmap(bool aFreeBuffer) {
|
||||
@ -1171,12 +1183,12 @@ void CanvasRenderingContext2D::SetStyleFromString(const nsACString& aStr,
|
||||
Style aWhichStyle) {
|
||||
MOZ_ASSERT(!aStr.IsVoid());
|
||||
|
||||
nscolor color;
|
||||
if (!ParseColor(aStr, &color)) {
|
||||
Maybe<nscolor> color = ParseColor(aStr);
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentState().SetColorStyle(aWhichStyle, color);
|
||||
CurrentState().SetColorStyle(aWhichStyle, *color);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::GetStyleAsUnion(
|
||||
@ -2325,12 +2337,12 @@ already_AddRefed<CanvasPattern> CanvasRenderingContext2D::CreatePattern(
|
||||
// shadows
|
||||
//
|
||||
void CanvasRenderingContext2D::SetShadowColor(const nsACString& aShadowColor) {
|
||||
nscolor color;
|
||||
if (!ParseColor(aShadowColor, &color)) {
|
||||
Maybe<nscolor> color = ParseColor(aShadowColor);
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentState().shadowColor = color;
|
||||
CurrentState().shadowColor = *color;
|
||||
}
|
||||
|
||||
//
|
||||
@ -3514,7 +3526,7 @@ bool CanvasRenderingContext2D::SetFontInternal(const nsACString& aFont,
|
||||
}
|
||||
|
||||
nsPresContext* c = presShell->GetPresContext();
|
||||
CacheKey key{aFont, c->RestyleManager()->GetRestyleGeneration()};
|
||||
FontStyleCacheKey key{aFont, c->RestyleManager()->GetRestyleGeneration()};
|
||||
auto entry = mFontStyleCache.Lookup(key);
|
||||
if (!entry) {
|
||||
FontStyleData newData;
|
||||
@ -5372,8 +5384,8 @@ void CanvasRenderingContext2D::DrawWindow(nsGlobalWindowInner& aWindow,
|
||||
return;
|
||||
}
|
||||
|
||||
nscolor backgroundColor;
|
||||
if (!ParseColor(aBgColor, &backgroundColor)) {
|
||||
Maybe<nscolor> backgroundColor = ParseColor(aBgColor);
|
||||
if (!backgroundColor) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
@ -5459,7 +5471,7 @@ void CanvasRenderingContext2D::DrawWindow(nsGlobalWindowInner& aWindow,
|
||||
|
||||
RefPtr<PresShell> presShell = presContext->PresShell();
|
||||
|
||||
Unused << presShell->RenderDocument(r, renderDocFlags, backgroundColor,
|
||||
Unused << presShell->RenderDocument(r, renderDocFlags, *backgroundColor,
|
||||
&thebes.ref());
|
||||
// If this canvas was contained in the drawn window, the pre-transaction
|
||||
// callback may have returned its DT. If so, we must reacquire it here.
|
||||
|
@ -133,6 +133,10 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
||||
}
|
||||
}
|
||||
|
||||
enum class ResolveCurrentColor : bool { No, Yes };
|
||||
Maybe<nscolor> ParseColor(const nsACString&,
|
||||
ResolveCurrentColor = ResolveCurrentColor::Yes);
|
||||
|
||||
void GetGlobalCompositeOperation(nsAString& aOp,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
void SetGlobalCompositeOperation(const nsAString& aOp,
|
||||
@ -572,9 +576,6 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
||||
void GetStyleAsUnion(OwningUTF8StringOrCanvasGradientOrCanvasPattern& aValue,
|
||||
Style aWhichStyle);
|
||||
|
||||
// Returns whether a color was successfully parsed.
|
||||
bool ParseColor(const nsACString& aString, nscolor* aColor);
|
||||
|
||||
static void StyleColorToString(const nscolor& aColor, nsACString& aStr);
|
||||
|
||||
// Returns whether a filter was successfully parsed.
|
||||
@ -1010,28 +1011,29 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
||||
return mStyleStack[mStyleStack.Length() - 1];
|
||||
}
|
||||
|
||||
struct CacheKey {
|
||||
CacheKey() : mFont(), mGeneration(0) {}
|
||||
CacheKey(const nsACString& aFont, uint64_t aGeneration)
|
||||
struct FontStyleCacheKey {
|
||||
FontStyleCacheKey() = default;
|
||||
FontStyleCacheKey(const nsACString& aFont, uint64_t aGeneration)
|
||||
: mFont(aFont), mGeneration(aGeneration) {}
|
||||
nsCString mFont;
|
||||
uint64_t mGeneration;
|
||||
uint64_t mGeneration = 0;
|
||||
};
|
||||
|
||||
struct FontStyleData {
|
||||
CacheKey mKey;
|
||||
FontStyleCacheKey mKey;
|
||||
nsCString mUsedFont;
|
||||
RefPtr<const ComputedStyle> mStyle;
|
||||
};
|
||||
|
||||
class FontStyleCache
|
||||
: public MruCache<CacheKey, FontStyleData, FontStyleCache> {
|
||||
: public MruCache<FontStyleCacheKey, FontStyleData, FontStyleCache> {
|
||||
public:
|
||||
static HashNumber Hash(const CacheKey& aKey) {
|
||||
static HashNumber Hash(const FontStyleCacheKey& aKey) {
|
||||
HashNumber hash = HashString(aKey.mFont);
|
||||
return AddToHash(hash, aKey.mGeneration);
|
||||
}
|
||||
static bool Match(const CacheKey& aKey, const FontStyleData& aVal) {
|
||||
static bool Match(const FontStyleCacheKey& aKey,
|
||||
const FontStyleData& aVal) {
|
||||
return aVal.mKey.mGeneration == aKey.mGeneration &&
|
||||
aVal.mKey.mFont == aKey.mFont;
|
||||
}
|
||||
@ -1039,6 +1041,24 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
||||
|
||||
FontStyleCache mFontStyleCache;
|
||||
|
||||
struct ColorStyleCacheEntry {
|
||||
nsCString mKey;
|
||||
Maybe<nscolor> mColor;
|
||||
bool mWasCurrentColor = false;
|
||||
};
|
||||
class ColorStyleCache
|
||||
: public MruCache<nsACString, ColorStyleCacheEntry, ColorStyleCache> {
|
||||
public:
|
||||
static HashNumber Hash(const nsACString& aKey) { return HashString(aKey); }
|
||||
static bool Match(const nsACString& aKey,
|
||||
const ColorStyleCacheEntry& aVal) {
|
||||
return aVal.mKey == aKey;
|
||||
}
|
||||
};
|
||||
ColorStyleCache mColorStyleCache;
|
||||
|
||||
ColorStyleCacheEntry ParseColorSlow(const nsACString&);
|
||||
|
||||
friend class CanvasGeneralPattern;
|
||||
friend class AdjustedTarget;
|
||||
friend class AdjustedTargetForShadow;
|
||||
|
Loading…
Reference in New Issue
Block a user