Skip to content

Commit

Permalink
Move logic for generated images from CSSValue types to the StyleImage…
Browse files Browse the repository at this point in the history
… types

https://bugs.webkit.org/show_bug.cgi?id=246594
rdar://101225901

Reviewed by Darin Adler.

In a step toward creating a comprehensive layering between the CSSValue types
and the Style types they resolve to, this change moves all of the logic that
used to be in the CSSValue derived types for generated images into their new
Style counterparts. This leaves the CSSValue side as immutable representations
of the parsed CSS (or an immutable representation of a computed CSS property)
that is capable of only a few operations:
   - equality
   - serialization
   - resolution to Style counterpart

This initial move does a pretty close approximation of just moving the logic
and state, in some cases having the Style type continue to store CSSValues,
but subsequent changes should change this so that we do conversion to lower
level types at creation time (e.g. use Length rather than CSSPrimitiveValue).
The one major exception is that we now reference other images as StyleImages
rather than CSSValues in the places where the types require input images
such as StyleCrossfadeImage and StyleFilterImage. This puts us in a strong
position to fix a bunch of long standing issues with animating between
various combinations of nested images.

Due to the simplification on the CSSValue side, we no longer need the
CSSImageGeneratorValue intermediate class, so it has been removed.

This change does not update CSSImageValue in the same way as the generated
image classes, as that has additional complications that should be handled
on their own.

* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/css/CSSImageGeneratorValue.cpp: Removed.
* Source/WebCore/css/CSSImageGeneratorValue.h: Removed.
Remove CSSImageGeneratorValue.

* Source/WebCore/animation/CSSPropertyAnimation.cpp:
(WebCore::blendFilter):
(WebCore::crossfadeBlend):
(WebCore::blendFunc):
Update to use StyleImages (and subclasses thereof) rather than the CSSValue
types, making the logic much closer to other blend primitives and allowing
the removal of a lot of unnecessary temporary allocations.

* Source/WebCore/css/CSSCanvasValue.cpp:
* Source/WebCore/css/CSSCanvasValue.h:
* Source/WebCore/css/CSSCrossfadeValue.cpp:
* Source/WebCore/css/CSSCrossfadeValue.h:
* Source/WebCore/css/CSSCursorImageValue.cpp:
* Source/WebCore/css/CSSCursorImageValue.h:
* Source/WebCore/css/CSSFilterImageValue.cpp:
* Source/WebCore/css/CSSFilterImageValue.h:
* Source/WebCore/css/CSSGradientValue.cpp:
* Source/WebCore/css/CSSGradientValue.h:
* Source/WebCore/css/CSSImageSetValue.cpp:
* Source/WebCore/css/CSSImageSetValue.h:
* Source/WebCore/css/CSSNamedImageValue.cpp:
* Source/WebCore/css/CSSNamedImageValue.h:
* Source/WebCore/css/CSSPaintImageValue.cpp:
* Source/WebCore/css/CSSPaintImageValue.h:
Move most of the logic and behaviors out of these classes and into
their Style counterparts. In some cases, member variable names were
expanded to make it more clear what they could hold in the surprising
cases where it was either an image or the `none` identifier.

* Source/WebCore/css/CSSCustomPropertyValue.cpp:
(WebCore::CSSCustomPropertyValue::equals const):
(WebCore::CSSCustomPropertyValue::customCSSText const):
* Source/WebCore/css/CSSCustomPropertyValue.h:
Remove unused creation function and subsequent dead code removing
it creates.

* Source/WebCore/css/CSSImageValue.cpp:
* Source/WebCore/css/CSSImageValue.h:
As this change focused on the generated image types, this class remains
relatively the same, but has its create methods cleaned up and replaces
the valueWithStylesResolved with the new direct createStyleImage. The
ResolvedURL type was also moved to CSSParserContext so it can be included
in more places with out cycles.

* Source/WebCore/css/CSSToStyleMap.cpp:
(WebCore::CSSToStyleMap::mapNinePieceImage):
* Source/WebCore/style/StyleBuilderConverter.h:
(WebCore::Style::isImageShape):
* Source/WebCore/style/StyleBuilderCustom.h:
(WebCore::Style::BuilderCustom::applyValueContent):
Now that there isn't a CSSImageGeneratorValue type, we use the existing
isImageGeneratorValue() function that does the same thing as an is<>.

* Source/WebCore/css/ComputedStyleExtractor.cpp:
(WebCore::valueForNinePieceImage):
(WebCore::ComputedStyleExtractor::currentColorOrValidColor):
(WebCore::contentToCSSValue):
(WebCore::shapePropertyValue):
(WebCore::ComputedStyleExtractor::valueForPropertyInStyle):
(WebCore::ComputedStyleExtractor::currentColorOrValidColor const): Deleted.
* Source/WebCore/css/ComputedStyleExtractor.h:
With the StyleImage subclasses taking on more responsibility, a bit more context
is now needed when generating computed values for them. To resolve this, we now
pass the currently computing RenderStyle to them in their renamed computedStyleValue()
methods (previously named cssValue()).

* Source/WebCore/css/StyleColor.cpp:
* Source/WebCore/css/StyleColor.h:
(WebCore::serializationForRenderTreeAsText): Deleted.
Remove unused function.

* Source/WebCore/css/parser/CSSParserContext.cpp:
* Source/WebCore/css/parser/CSSParserContext.h:
Move ResolvedURL here from CSSImageValue to allow use in more places
with including CSSImageValue. It also makes more sense here as this
is where they are created.

* Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp:
(WebCore::CSSPropertyParserHelpers::consumeGradientColorStops):
Remove now removed third argument.
(WebCore::CSSPropertyParserHelpers::consumeCrossFade):
(WebCore::CSSPropertyParserHelpers::consumeFilterImage):
Add some notes and FIXMEs about the implementation and rename a few variables
for clarity.

* Source/WebCore/html/CanvasBase.cpp:
* Source/WebCore/html/CanvasBase.h:
(WebCore::CanvasObserver::isStyleCanvasImage const):
(WebCore::CanvasObserver::isCanvasObserverProxy const): Deleted.
* Source/WebCore/html/HTMLCanvasElement.cpp:
(WebCore::HTMLCanvasElement::~HTMLCanvasElement):
Update to reflect that now the StyleCanvasImage and not the CSSCanvasValue::CanvasObserverProxy
is the observer for canvas() images.

* Source/WebCore/html/HTMLBodyElement.cpp:
(WebCore::HTMLBodyElement::collectPresentationalHintsForAttribute):
Pass the initiatorName via the create function rather than an
explicit getter, now that the create function supports that. This
allows the type to move toward immutability.

* Source/WebCore/html/HTMLInputElement.cpp:
(WebCore::autoFillStrongPasswordMaskImage):
(WebCore::HTMLInputElement::createInnerTextStyle):
Now that StyleGradientImage is more than just a wrapper around CSSGradientValue, we can
use it directly for the image mask, bypassing the need for a CSS value entirely.

* Source/WebCore/rendering/style/StyleCachedImage.cpp:
(WebCore::StyleCachedImage::create):
(WebCore::StyleCachedImage::copyOverridingScaleFactor):
* Source/WebCore/rendering/style/StyleCachedImage.h:
While mostly unchanged behavior wise, update to conform to some of the
idiomatic norms of the StyleImage types, adding a typed equals() function
(used by the CSSPropertyAnimations), and an explicit copyOverridingScaleFactor
create function used by StyleMultiImage to avoid that class knowing that
getting the internal CSSValue was possible (since it won't be in the future).

* Source/WebCore/rendering/style/StyleCanvasImage.cpp:
* Source/WebCore/rendering/style/StyleCanvasImage.h:
* Source/WebCore/rendering/style/StyleCrossfadeImage.cpp:
* Source/WebCore/rendering/style/StyleCrossfadeImage.h:
* Source/WebCore/rendering/style/StyleCursorImage.cpp:
* Source/WebCore/rendering/style/StyleCursorImage.h:
* Source/WebCore/rendering/style/StyleFilterImage.cpp:
* Source/WebCore/rendering/style/StyleFilterImage.h:
* Source/WebCore/rendering/style/StyleGradientImage.cpp:
* Source/WebCore/rendering/style/StyleGradientImage.h:
* Source/WebCore/rendering/style/StyleImageSet.cpp:
* Source/WebCore/rendering/style/StyleImageSet.h:
* Source/WebCore/rendering/style/StyleNamedImage.cpp:
* Source/WebCore/rendering/style/StyleNamedImage.h:
* Source/WebCore/rendering/style/StylePaintImage.cpp:
* Source/WebCore/rendering/style/StylePaintImage.h:
Move logic and state from the CSSValue counterparts, aiming to change as little
as possible. This means that in some cases we are storing the data in a non
optimal way. For example, we store gradient parameters as the CSSPrimitiveValues
to keep the current (and incorrect) behavior for color serialization. This
allows this change to be behavior neutral, with the fixes coming on their own.

* Source/WebCore/rendering/style/StyleGeneratedImage.cpp:
* Source/WebCore/rendering/style/StyleGeneratedImage.h:
(WebCore::StyleGeneratedImage:: const):
Move the logic from CSSImageGeneratorValue for generated image caching / eviction
and client tracking. Also adds additional virtual functions for the generated images,
didAddClient/didRemoveClient to allow them to react to clients. This is used by
StyleCanvasImage, for example, to notify the inspector.

* Source/WebCore/rendering/style/StyleImage.h:
Rename cssValue() function to computedStyleValue() and pass in the computing RenderStyle.
This is needed now that the StyleImages don't store pointers to their original CSSValues
anymore.

* Source/WebCore/rendering/style/StyleMultiImage.cpp:
* Source/WebCore/rendering/style/StyleMultiImage.h:
Move ImageWithScale here (it was previously defined in CSSImageSetValue)
and replace the CSSValue with a StyleImage. This means we now can track
the image set options as StyleImages, allowing the removal of creates
in StyleMultiImage::load (except the one when you have a StyleCachedImage
with a different scale factor).

* Source/WebCore/style/StyleBuilderState.cpp:
(WebCore::Style::BuilderState::createStyleImage):
(WebCore::Style::BuilderState::resolveImageStyles): Deleted.
* Source/WebCore/style/StyleBuilderState.h:
Remove resolveImageStyles entirely, merging resolution into style
creation, and converting to taking const CSSValue references,
removing the possibility for the confusing interim resolved state
to return.

* Source/WebCore/svg/SVGCursorElement.cpp:
* Source/WebCore/svg/SVGCursorElement.h:
Updated to use StyleCursorImage as the client.

Canonical link: https://commits.webkit.org/255897@main
  • Loading branch information
weinig authored and Sam Weinig committed Oct 23, 2022
1 parent e625d45 commit 32d57af
Show file tree
Hide file tree
Showing 72 changed files with 2,442 additions and 2,964 deletions.
1 change: 0 additions & 1 deletion Source/WebCore/Sources.txt
Expand Up @@ -772,7 +772,6 @@ css/CSSGridIntegerRepeatValue.cpp
css/CSSGridLineNamesValue.cpp
css/CSSGridTemplateAreasValue.cpp
css/CSSGroupingRule.cpp
css/CSSImageGeneratorValue.cpp
css/CSSImageSetValue.cpp
css/CSSImageValue.cpp
css/CSSImportRule.cpp
Expand Down
6 changes: 0 additions & 6 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Expand Up @@ -4266,7 +4266,6 @@
BC2273040E82F1E600E7F975 /* StyleInheritedData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2273020E82F1E600E7F975 /* StyleInheritedData.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC2274790E8366E200E7F975 /* SVGRenderStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2274750E8366E200E7F975 /* SVGRenderStyle.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC22747B0E8366E200E7F975 /* SVGRenderStyleDefs.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2274770E8366E200E7F975 /* SVGRenderStyleDefs.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC23EE920DAED2BC009FDC91 /* CSSImageGeneratorValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC23EE910DAED2BC009FDC91 /* CSSImageGeneratorValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC23F0DB0DAFF4A4009FDC91 /* GeneratedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = BC23F0DA0DAFF4A4009FDC91 /* GeneratedImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC274B2F140EBEB200EADFA6 /* CSSBorderImageSliceValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC274B2E140EBEB200EADFA6 /* CSSBorderImageSliceValue.h */; };
BC2B41172732F41E00A2D191 /* ModelPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2B41132732F06200A2D191 /* ModelPlayer.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -15777,8 +15776,6 @@
BC2274760E8366E200E7F975 /* SVGRenderStyleDefs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGRenderStyleDefs.cpp; sourceTree = "<group>"; };
BC2274770E8366E200E7F975 /* SVGRenderStyleDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGRenderStyleDefs.h; sourceTree = "<group>"; };
BC23E4E00DAACE0F009FDC91 /* CSSGradientValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSGradientValue.cpp; sourceTree = "<group>"; };
BC23E76B0DAE88A9009FDC91 /* CSSImageGeneratorValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSImageGeneratorValue.cpp; sourceTree = "<group>"; };
BC23EE910DAED2BC009FDC91 /* CSSImageGeneratorValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSImageGeneratorValue.h; sourceTree = "<group>"; };
BC23F0DA0DAFF4A4009FDC91 /* GeneratedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedImage.h; sourceTree = "<group>"; };
BC2441C30E8B65D00055320F /* ScrollView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollView.cpp; sourceTree = "<group>"; };
BC274B2E140EBEB200EADFA6 /* CSSBorderImageSliceValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSBorderImageSliceValue.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -32756,8 +32753,6 @@
FB3056C1169E5DAC0096A232 /* CSSGroupingRule.h */,
930AAC9B250EC2F30013DA9F /* CSSGroupingRule.idl */,
BC772B360C4EA91E0083285F /* CSSHelper.h */,
BC23E76B0DAE88A9009FDC91 /* CSSImageGeneratorValue.cpp */,
BC23EE910DAED2BC009FDC91 /* CSSImageGeneratorValue.h */,
9393E5FD151A99F200066F06 /* CSSImageSetValue.cpp */,
9393E5FE151A99F200066F06 /* CSSImageSetValue.h */,
A80E6CD40A1989CA007FB8C5 /* CSSImageValue.cpp */,
Expand Down Expand Up @@ -35185,7 +35180,6 @@
CD3E252418046BCD00E27F56 /* CSSGridTemplateAreasValue.h in Headers */,
FB3056C2169E5DAC0096A232 /* CSSGroupingRule.h in Headers */,
BC772B3C0C4EA91E0083285F /* CSSHelper.h in Headers */,
BC23EE920DAED2BC009FDC91 /* CSSImageGeneratorValue.h in Headers */,
9393E600151A99F200066F06 /* CSSImageSetValue.h in Headers */,
A80E6CFA0A1989CA007FB8C5 /* CSSImageValue.h in Headers */,
A80E6CF60A1989CA007FB8C5 /* CSSImportRule.h in Headers */,
Expand Down
105 changes: 40 additions & 65 deletions Source/WebCore/animation/CSSPropertyAnimation.cpp
Expand Up @@ -31,10 +31,6 @@
#include "CSSPropertyAnimation.h"

#include "AnimationUtilities.h"
#include "CSSCrossfadeValue.h"
#include "CSSFilterImageValue.h"
#include "CSSImageGeneratorValue.h"
#include "CSSImageValue.h"
#include "CSSPrimitiveValue.h"
#include "CSSPropertyBlendingClient.h"
#include "CSSPropertyNames.h"
Expand Down Expand Up @@ -381,17 +377,10 @@ static inline FilterOperations blendFunc(const FilterOperations& from, const Fil
return result;
}

static inline RefPtr<StyleImage> blendFilter(CachedImage* image, const FilterOperations& from, const FilterOperations& to, const CSSPropertyBlendingContext& context)
static inline RefPtr<StyleImage> blendFilter(RefPtr<StyleImage> inputImage, const FilterOperations& from, const FilterOperations& to, const CSSPropertyBlendingContext& context)
{
ASSERT(image);
FilterOperations filterResult = blendFilterOperations(from, to, context);

auto imageValue = CSSImageValue::create(*image);
auto filterValue = ComputedStyleExtractor::valueForFilter(context.client->currentStyle(), filterResult, ComputedStyleExtractor::AdjustPixelValuesForComputedStyle::No);

auto result = CSSFilterImageValue::create(WTFMove(imageValue), WTFMove(filterValue));
result.get().setFilterOperations(filterResult);
return StyleFilterImage::create(WTFMove(result));
auto filterResult = blendFilterOperations(from, to, context);
return StyleFilterImage::create(WTFMove(inputImage), WTFMove(filterResult));
}

static inline Visibility blendFunc(Visibility from, Visibility to, const CSSPropertyBlendingContext& context)
Expand Down Expand Up @@ -457,23 +446,17 @@ static inline Vector<SVGLengthValue> blendFunc(const Vector<SVGLengthValue>& fro
return result;
}

static inline RefPtr<StyleImage> crossfadeBlend(StyleCachedImage* fromStyleImage, StyleCachedImage* toStyleImage, const CSSPropertyBlendingContext& context)
static inline RefPtr<StyleImage> crossfadeBlend(StyleCachedImage& fromStyleImage, StyleCachedImage& toStyleImage, const CSSPropertyBlendingContext& context)
{
// If progress is at one of the extremes, we want getComputedStyle to show the image,
// not a completed cross-fade, so we hand back one of the existing images.
if (!context.progress)
return fromStyleImage;
return &fromStyleImage;
if (context.progress == 1)
return toStyleImage;
if (!fromStyleImage->cachedImage() || !toStyleImage->cachedImage())
return toStyleImage;

auto fromImageValue = CSSImageValue::create(*fromStyleImage->cachedImage());
auto toImageValue = CSSImageValue::create(*toStyleImage->cachedImage());
auto percentageValue = CSSPrimitiveValue::create(context.progress, CSSUnitType::CSS_NUMBER);

auto crossfadeValue = CSSCrossfadeValue::create(WTFMove(fromImageValue), WTFMove(toImageValue), WTFMove(percentageValue));
return StyleCrossfadeImage::create(WTFMove(crossfadeValue));
return &toStyleImage;
if (!fromStyleImage.cachedImage() || !toStyleImage.cachedImage())
return &toStyleImage;
return StyleCrossfadeImage::create(&fromStyleImage, &toStyleImage, context.progress, false);
}

static inline RefPtr<StyleImage> blendFunc(StyleImage* from, StyleImage* to, const CSSPropertyBlendingContext& context)
Expand All @@ -493,52 +476,44 @@ static inline RefPtr<StyleImage> blendFunc(StyleImage* from, StyleImage* to, con
return to;

// Animation between two generated images. Cross fade for all other cases.
if (is<StyleGeneratedImage>(*from) && is<StyleGeneratedImage>(*to)) {
CSSImageGeneratorValue& fromGenerated = downcast<StyleGeneratedImage>(*from).imageValue();
CSSImageGeneratorValue& toGenerated = downcast<StyleGeneratedImage>(*to).imageValue();

if (is<CSSFilterImageValue>(fromGenerated) && is<CSSFilterImageValue>(toGenerated)) {
// Animation of generated images just possible if input images are equal.
// Otherwise fall back to cross fade animation.
CSSFilterImageValue& fromFilter = downcast<CSSFilterImageValue>(fromGenerated);
CSSFilterImageValue& toFilter = downcast<CSSFilterImageValue>(toGenerated);
if (fromFilter.equalInputImages(toFilter) && fromFilter.cachedImage())
return blendFilter(fromFilter.cachedImage(), fromFilter.filterOperations(), toFilter.filterOperations(), context);
if (is<StyleFilterImage>(*from) && is<StyleFilterImage>(*to)) {
// Animation of generated images just possible if input images are equal.
// Otherwise fall back to cross fade animation.
auto& fromFilter = downcast<StyleFilterImage>(*from);
auto& toFilter = downcast<StyleFilterImage>(*to);

if (fromFilter.equalInputImages(toFilter) && is<StyleCachedImage>(fromFilter.inputImage()))
return blendFilter(fromFilter.inputImage(), fromFilter.filterOperations(), toFilter.filterOperations(), context);
} else if (is<StyleCrossfadeImage>(*from) && is<StyleCrossfadeImage>(*to)) {
auto& fromCrossfade = downcast<StyleCrossfadeImage>(*from);
auto& toCrossfade = downcast<StyleCrossfadeImage>(*to);

if (fromCrossfade.equalInputImages(toCrossfade)) {
if (auto crossfadeBlend = toCrossfade.blend(fromCrossfade, context))
return crossfadeBlend;
}
} else if (is<StyleFilterImage>(*from) && is<StyleCachedImage>(*to)) {
auto& fromFilter = downcast<StyleFilterImage>(*from);
auto fromFilterInputImage = fromFilter.inputImage();

if (is<CSSCrossfadeValue>(fromGenerated) && is<CSSCrossfadeValue>(toGenerated)) {
CSSCrossfadeValue& fromCrossfade = downcast<CSSCrossfadeValue>(fromGenerated);
CSSCrossfadeValue& toCrossfade = downcast<CSSCrossfadeValue>(toGenerated);
if (fromCrossfade.equalInputImages(toCrossfade)) {
if (auto crossfadeBlend = toCrossfade.blend(fromCrossfade, context))
return StyleCrossfadeImage::create(*crossfadeBlend);
}
}
if (is<StyleCachedImage>(fromFilterInputImage) && downcast<StyleCachedImage>(*to).equals(downcast<StyleCachedImage>(*fromFilterInputImage)))
return blendFilter(WTFMove(fromFilterInputImage), fromFilter.filterOperations(), FilterOperations(), context);
} else if (is<StyleCachedImage>(*from) && is<StyleFilterImage>(*to)) {
auto& toFilter = downcast<StyleFilterImage>(*to);
auto toFilterInputImage = toFilter.inputImage();

// FIXME: Add support for animation between two *gradient() functions.
// https://bugs.webkit.org/show_bug.cgi?id=119956
} else if (is<StyleGeneratedImage>(*from) && is<StyleCachedImage>(*to)) {
CSSImageGeneratorValue& fromGenerated = downcast<StyleGeneratedImage>(*from).imageValue();
if (is<CSSFilterImageValue>(fromGenerated)) {
CSSFilterImageValue& fromFilter = downcast<CSSFilterImageValue>(fromGenerated);
if (fromFilter.cachedImage() && downcast<StyleCachedImage>(*to).cachedImage() == fromFilter.cachedImage())
return blendFilter(fromFilter.cachedImage(), fromFilter.filterOperations(), FilterOperations(), context);
}
// FIXME: Add interpolation between cross-fade and image source.
} else if (is<StyleCachedImage>(*from) && is<StyleGeneratedImage>(*to)) {
CSSImageGeneratorValue& toGenerated = downcast<StyleGeneratedImage>(*to).imageValue();
if (is<CSSFilterImageValue>(toGenerated)) {
CSSFilterImageValue& toFilter = downcast<CSSFilterImageValue>(toGenerated);
if (toFilter.cachedImage() && downcast<StyleCachedImage>(*from).cachedImage() == toFilter.cachedImage())
return blendFilter(toFilter.cachedImage(), FilterOperations(), toFilter.filterOperations(), context);
}
// FIXME: Add interpolation between image source and cross-fade.
if (is<StyleCachedImage>(toFilterInputImage) && downcast<StyleCachedImage>(*from).equals(downcast<StyleCachedImage>(*toFilterInputImage)))
return blendFilter(WTFMove(toFilterInputImage), FilterOperations(), toFilter.filterOperations(), context);
}

if (is<StyleCachedImage>(*from) && is<StyleCachedImage>(*to))
return crossfadeBlend(downcast<StyleCachedImage>(*from), downcast<StyleCachedImage>(*to), context);

// FIXME: Add support for animation between two *gradient() functions.
// https://bugs.webkit.org/show_bug.cgi?id=119956

// FIXME: Add support cross fade between cached and generated images.
// https://bugs.webkit.org/show_bug.cgi?id=78293
if (is<StyleCachedImage>(*from) && is<StyleCachedImage>(*to))
return crossfadeBlend(downcast<StyleCachedImage>(from), downcast<StyleCachedImage>(to), context);

return to;
}
Expand Down
62 changes: 10 additions & 52 deletions Source/WebCore/css/CSSCanvasValue.cpp
Expand Up @@ -26,73 +26,31 @@
#include "config.h"
#include "CSSCanvasValue.h"

#include "RenderElement.h"
#include "StyleCanvasImage.h"

namespace WebCore {

CSSCanvasValue::~CSSCanvasValue()
CSSCanvasValue::CSSCanvasValue(String&& name)
: CSSValue { CanvasClass }
, m_name { WTFMove(name) }
{
if (m_element)
m_element->removeObserver(m_canvasObserver);
}

CSSCanvasValue::~CSSCanvasValue() = default;

String CSSCanvasValue::customCSSText() const
{
return makeString("-webkit-canvas(", m_name, ')');
}

void CSSCanvasValue::canvasChanged(HTMLCanvasElement&, const std::optional<FloatRect>& changedRect)
{
if (!changedRect)
return;

auto imageChangeRect = enclosingIntRect(changedRect.value());
for (auto it = clients().begin(), end = clients().end(); it != end; ++it)
it->key->imageChanged(static_cast<WrappedImagePtr>(this), &imageChangeRect);
}

void CSSCanvasValue::canvasResized(HTMLCanvasElement&)
{
for (auto it = clients().begin(), end = clients().end(); it != end; ++it)
it->key->imageChanged(static_cast<WrappedImagePtr>(this));
}

void CSSCanvasValue::canvasDestroyed(HTMLCanvasElement& element)
{
ASSERT_UNUSED(&element, &element == m_element);
m_element = nullptr;
}

FloatSize CSSCanvasValue::fixedSize(const RenderElement& renderer)
{
if (HTMLCanvasElement* elt = element(renderer.document()))
return FloatSize(elt->width(), elt->height());
return { };
}

HTMLCanvasElement* CSSCanvasValue::element(Document& document)
{
if (!m_element) {
m_element = document.getCSSCanvasElement(m_name);
if (!m_element)
return nullptr;
m_element->addObserver(m_canvasObserver);
}
return m_element;
}

RefPtr<Image> CSSCanvasValue::image(RenderElement& renderer, const FloatSize& /*size*/)
bool CSSCanvasValue::equals(const CSSCanvasValue& other) const
{
ASSERT(clients().contains(&renderer));
HTMLCanvasElement* element = this->element(renderer.document());
if (!element || !element->buffer())
return nullptr;
return element->copiedImage();
return m_name == other.m_name;
}

bool CSSCanvasValue::equals(const CSSCanvasValue& other) const
RefPtr<StyleImage> CSSCanvasValue::createStyleImage(Style::BuilderState&) const
{
return m_name == other.m_name;
return StyleCanvasImage::create(m_name);
}

} // namespace WebCore
82 changes: 8 additions & 74 deletions Source/WebCore/css/CSSCanvasValue.h
Expand Up @@ -25,99 +25,33 @@

#pragma once

#include "CSSImageGeneratorValue.h"
#include "CanvasBase.h"
#include "HTMLCanvasElement.h"
#include "RenderElement.h"
#include "CSSValue.h"
#include <wtf/text/WTFString.h>

namespace WebCore {

class StyleImage;

namespace Style {
class BuilderState;
}

class Document;

class CSSCanvasValue final : public CSSImageGeneratorValue {
class CSSCanvasValue final : public CSSValue {
public:
static Ref<CSSCanvasValue> create(const String& name) { return adoptRef(*new CSSCanvasValue(name)); }
static Ref<CSSCanvasValue> create(String name) { return adoptRef(*new CSSCanvasValue(WTFMove(name))); }
~CSSCanvasValue();

String customCSSText() const;

RefPtr<Image> image(RenderElement&, const FloatSize&);
bool isFixedSize() const { return true; }
FloatSize fixedSize(const RenderElement&);

HTMLCanvasElement* element() const { return m_element; }

bool isPending() const { return false; }
void loadSubimages(CachedResourceLoader&, const ResourceLoaderOptions&) { }

bool equals(const CSSCanvasValue&) const;

// NOTE: We put the CanvasObserver in a member instead of inheriting from it
// to avoid adding a vptr to CSSCanvasValue.
class CanvasObserverProxy final : public CanvasObserver {
public:
explicit CanvasObserverProxy(CSSCanvasValue& ownerValue)
: m_ownerValue(ownerValue)
{
}

bool isCanvasObserverProxy() const final { return true; }

const CSSCanvasValue& ownerValue() const { return m_ownerValue; }

private:
void canvasChanged(CanvasBase& canvasBase, const std::optional<FloatRect>& changedRect) final
{
ASSERT(is<HTMLCanvasElement>(canvasBase));
m_ownerValue.canvasChanged(downcast<HTMLCanvasElement>(canvasBase), changedRect);
}
void canvasResized(CanvasBase& canvasBase) final
{
ASSERT(is<HTMLCanvasElement>(canvasBase));
m_ownerValue.canvasResized(downcast<HTMLCanvasElement>(canvasBase));
}
void canvasDestroyed(CanvasBase& canvasBase) final
{
ASSERT(is<HTMLCanvasElement>(canvasBase));
m_ownerValue.canvasDestroyed(downcast<HTMLCanvasElement>(canvasBase));
}

CSSCanvasValue& m_ownerValue;
};

Ref<CSSCanvasValue> valueWithStylesResolved(Style::BuilderState&) { return *this; }
RefPtr<StyleImage> createStyleImage(Style::BuilderState&) const;

private:
explicit CSSCanvasValue(const String& name)
: CSSImageGeneratorValue(CanvasClass)
, m_canvasObserver(*this)
, m_name(name)
{
}

void canvasChanged(HTMLCanvasElement&, const std::optional<FloatRect>& changedRect);
void canvasResized(HTMLCanvasElement&);
void canvasDestroyed(HTMLCanvasElement&);
explicit CSSCanvasValue(String&&);

HTMLCanvasElement* element(Document&);

CanvasObserverProxy m_canvasObserver;

// The name of the canvas.
String m_name;
// The document supplies the element and owns it.
HTMLCanvasElement* m_element { nullptr };
};

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSCanvasValue, isCanvasValue())

SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::CSSCanvasValue::CanvasObserverProxy)
static bool isType(const WebCore::CanvasObserver& canvasObserver) { return canvasObserver.isCanvasObserverProxy(); }
SPECIALIZE_TYPE_TRAITS_END()

0 comments on commit 32d57af

Please sign in to comment.