FloatSize CSSCrossfadeValue::fixedSize(const RenderElement& renderer) { float percentage = m_percentageValue->floatValue(); float inversePercentage = 1 - percentage; // FIXME: Skip Content Security Policy check when cross fade is applied to an element in a user agent shadow tree. // See <https://bugs.webkit.org/show_bug.cgi?id=146663>. auto options = CachedResourceLoader::defaultCachedResourceOptions(); auto& cachedResourceLoader = renderer.document().cachedResourceLoader(); auto* cachedFromImage = cachedImageForCSSValue(m_fromValue, cachedResourceLoader, options); auto* cachedToImage = cachedImageForCSSValue(m_toValue, cachedResourceLoader, options); if (!cachedFromImage || !cachedToImage) return FloatSize(); FloatSize fromImageSize = cachedFromImage->imageForRenderer(&renderer)->size(); FloatSize toImageSize = cachedToImage->imageForRenderer(&renderer)->size(); // Rounding issues can cause transitions between images of equal size to return // a different fixed size; avoid performing the interpolation if the images are the same size. if (fromImageSize == toImageSize) return fromImageSize; return fromImageSize * inversePercentage + toImageSize * percentage; }
static inline void removeFromCacheAndInvalidateDependencies(RenderElement& renderer, bool needsLayout) { if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) { if (RenderSVGResourceFilter* filter = resources->filter()) filter->removeClientFromCache(renderer); if (RenderSVGResourceMasker* masker = resources->masker()) masker->removeClientFromCache(renderer); if (RenderSVGResourceClipper* clipper = resources->clipper()) clipper->removeClientFromCache(renderer); } if (!renderer.element() || !renderer.element()->isSVGElement()) return; HashSet<SVGElement*>* dependencies = renderer.document().accessSVGExtensions().setOfElementsReferencingTarget(downcast<SVGElement>(renderer.element())); if (!dependencies) return; // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive // reference graph adjustments on changes, so we need to break possible cycles here. static NeverDestroyed<HashSet<SVGElement*>> invalidatingDependencies; for (auto* element : *dependencies) { if (auto* renderer = element->renderer()) { if (UNLIKELY(!invalidatingDependencies.get().add(element).isNewEntry)) { // Reference cycle: we are in process of invalidating this dependant. continue; } RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer, needsLayout); invalidatingDependencies.get().remove(element); } } }
bool AnimationController::updateAnimations(RenderElement& renderer, const RenderStyle& newStyle, std::unique_ptr<RenderStyle>& animatedStyle) { auto* oldStyle = renderer.hasInitializedStyle() ? &renderer.style() : nullptr; if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.animations() && !newStyle.transitions())) return false; if (renderer.document().pageCacheState() != Document::NotInPageCache) return false; // Don't run transitions when printing. if (renderer.view().printing()) return false; // Fetch our current set of implicit animations from a hashtable. We then compare them // against the animations in the style and make sure we're in sync. If destination values // have changed, we reset the animation. We then do a blend to get new values and we return // a new style. // We don't support anonymous pseudo elements like :first-line or :first-letter. ASSERT(renderer.element()); CompositeAnimation& rendererAnimations = m_data->ensureCompositeAnimation(renderer); bool animationStateChanged = rendererAnimations.animate(renderer, oldStyle, newStyle, animatedStyle); if (renderer.parent() || newStyle.animations() || (oldStyle && oldStyle->animations())) { m_data->updateAnimationTimerForRenderer(renderer); #if ENABLE(REQUEST_ANIMATION_FRAME) renderer.view().frameView().scheduleAnimation(); #endif } return animationStateChanged; }
PassRef<RenderStyle> AnimationController::updateAnimations(RenderElement& renderer, PassRef<RenderStyle> newStyle) { // Don't do anything if we're in the cache if (renderer.document().inPageCache()) return newStyle; RenderStyle* oldStyle = renderer.hasInitializedStyle() ? &renderer.style() : nullptr; if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.get().animations() && !newStyle.get().transitions())) return newStyle; // Don't run transitions when printing. if (renderer.view().printing()) return newStyle; // Fetch our current set of implicit animations from a hashtable. We then compare them // against the animations in the style and make sure we're in sync. If destination values // have changed, we reset the animation. We then do a blend to get new values and we return // a new style. // We don't support anonymous pseudo elements like :first-line or :first-letter. ASSERT(renderer.element()); Ref<RenderStyle> newStyleBeforeAnimation(std::move(newStyle)); CompositeAnimation& rendererAnimations = m_data->ensureCompositeAnimation(&renderer); auto blendedStyle = rendererAnimations.animate(renderer, oldStyle, newStyleBeforeAnimation.get()); if (renderer.parent() || newStyleBeforeAnimation->animations() || (oldStyle && oldStyle->animations())) { m_data->updateAnimationTimerForRenderer(&renderer); #if ENABLE(REQUEST_ANIMATION_FRAME) renderer.view().frameView().scheduleAnimation(); #endif } if (&blendedStyle.get() != &newStyleBeforeAnimation.get()) { // If the animations/transitions change opacity or transform, we need to update // the style to impose the stacking rules. Note that this is also // done in StyleResolver::adjustRenderStyle(). if (blendedStyle.get().hasAutoZIndex() && (blendedStyle.get().opacity() < 1.0f || blendedStyle.get().hasTransform())) blendedStyle.get().setZIndex(0); } return blendedStyle; }
LayoutRect AccessibilityListBoxOption::elementRect() const { LayoutRect rect; if (!m_optionElement) return rect; HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode(); if (!listBoxParentNode) return rect; RenderElement* listBoxRenderer = listBoxParentNode->renderer(); if (!listBoxRenderer) return rect; LayoutRect parentRect = listBoxRenderer->document().axObjectCache()->getOrCreate(listBoxRenderer)->boundingBoxRect(); int index = listBoxOptionIndex(); if (index != -1) rect = downcast<RenderListBox>(*listBoxRenderer).itemBoundingBoxRect(parentRect.location(), index); return rect; }