void StyleBuilderFunctions::applyValueCSSPropertyDirection(StyleResolverState& state, CSSValue* value) { state.style()->setDirection(*toCSSPrimitiveValue(value)); Element* element = state.element(); if (element && element == element->document().documentElement()) element->document().setDirectionSetOnDocumentElement(true); }
void DeferredLegacyStyleInterpolation::apply(StyleResolverState& state) const { RefPtrWillBeRawPtr<LegacyStyleInterpolation> innerInterpolation = LegacyStyleInterpolation::create( StyleResolver::createAnimatableValueSnapshot(*state.element(), m_id, *m_startCSSValue, *state.style()), StyleResolver::createAnimatableValueSnapshot(*state.element(), m_id, *m_endCSSValue, *state.style()), m_id); innerInterpolation->interpolate(m_cachedIteration, m_cachedFraction); innerInterpolation->apply(state); }
void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult) { const Element* element = state.element(); ASSERT(element); INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply); unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0; bool applyInheritedOnly = false; const CachedMatchedProperties* cachedMatchedProperties = cacheHash ? m_matchedPropertiesCache.find(cacheHash, state, matchResult) : 0; if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) { INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit); // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the // element context. This is fast and saves memory by reusing the style data structures. state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get()); if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && (state.style()->userModify() == READ_ONLY)) { INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit); // If the cache item parent style has identical inherited properties to the current parent style then the // resulting style will be identical too. We copy the inherited properties over from the cache and are done. state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get()); return; } applyInheritedOnly = true; } state.setLineHeightValue(0); applyMatchedProperties<HighPriorityProperties>(state, matchResult, applyInheritedOnly); // If our font got dirtied, go ahead and update it now. updateFont(state); // Line-height is set when we are sure we decided on the font-size. if (state.lineHeightValue()) StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue()); // Many properties depend on the font. If it changes we just apply all properties. if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription()) applyInheritedOnly = false; applyMatchedProperties<LowPriorityProperties>(state, matchResult, applyInheritedOnly); if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) { INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded); m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult); } ASSERT(!state.fontBuilder().fontDirty()); }
void DeferredLegacyStyleInterpolation::apply(StyleResolverState& state) const { if (m_outdated || !state.element()->elementAnimations() || !state.element()->elementAnimations()->isAnimationStyleChange()) { RefPtr<AnimatableValue> startAnimatableValue; RefPtr<AnimatableValue> endAnimatableValue; // Snapshot underlying values for neutral keyframes first because non-neutral keyframes will mutate the StyleResolverState. if (!m_endCSSValue) { endAnimatableValue = StyleResolver::createAnimatableValueSnapshot(state, m_id, m_endCSSValue.get()); startAnimatableValue = StyleResolver::createAnimatableValueSnapshot(state, m_id, m_startCSSValue.get()); } else { startAnimatableValue = StyleResolver::createAnimatableValueSnapshot(state, m_id, m_startCSSValue.get()); endAnimatableValue = StyleResolver::createAnimatableValueSnapshot(state, m_id, m_endCSSValue.get()); } m_innerInterpolation = LegacyStyleInterpolation::create(startAnimatableValue, endAnimatableValue, m_id); m_outdated = false; } m_innerInterpolation->interpolate(m_cachedIteration, m_cachedFraction); m_innerInterpolation->apply(state); }
void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& state, CSSValue* value) { state.style()->clearCursorList(); if (value->isValueList()) { CSSValueList* list = toCSSValueList(value); int len = list->length(); state.style()->setCursor(CURSOR_AUTO); for (int i = 0; i < len; i++) { CSSValue* item = list->item(i); if (item->isCursorImageValue()) { CSSCursorImageValue* image = toCSSCursorImageValue(item); if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style. state.style()->setUnique(); state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpotSpecified(), image->hotSpot()); } else { state.style()->setCursor(*toCSSPrimitiveValue(item)); } } } else { state.style()->setCursor(*toCSSPrimitiveValue(value)); } }
AtomicString StyleBuilderConverter::convertFragmentIdentifier(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->isURI()) return SVGURIReference::fragmentIdentifierFromIRIString(primitiveValue->getStringValue(), state.element()->treeScope()); return nullAtom; }
void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value) { // list of string, uri, counter, attr, i bool didSet = false; for (auto& item : toCSSValueList(*value)) { if (item->isImageGeneratorValue()) { state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item.get())), didSet); didSet = true; } else if (item->isImageSetValue()) { state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item.get())), didSet); didSet = true; } if (item->isImageValue()) { state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item.get())), didSet); didSet = true; continue; } if (item->isCounterValue()) { CSSCounterValue* counterValue = toCSSCounterValue(item.get()); EListStyleType listStyleType = NoneListStyle; CSSValueID listStyleIdent = counterValue->listStyle(); if (listStyleIdent != CSSValueNone) listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator()))); state.style()->setContent(counter.release(), didSet); didSet = true; } if (item->isFunctionValue()) { CSSFunctionValue* functionValue = toCSSFunctionValue(item.get()); ASSERT(functionValue->functionType() == CSSValueAttr); // FIXME: Can a namespace be specified for an attr(foo)? if (state.style()->styleType() == NOPSEUDO) state.style()->setUnique(); else state.parentStyle()->setUnique(); QualifiedName attr(nullAtom, AtomicString(toCSSPrimitiveValue(functionValue->item(0))->getStringValue()), nullAtom); const AtomicString& value = state.element()->getAttribute(attr); state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); didSet = true; } if (!item->isPrimitiveValue()) continue; CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item.get()); if (contentValue->isString()) { state.style()->setContent(contentValue->getStringValue().impl(), didSet); didSet = true; } else { switch (contentValue->getValueID()) { case CSSValueOpenQuote: state.style()->setContent(OPEN_QUOTE, didSet); didSet = true; break; case CSSValueCloseQuote: state.style()->setContent(CLOSE_QUOTE, didSet); didSet = true; break; case CSSValueNoOpenQuote: state.style()->setContent(NO_OPEN_QUOTE, didSet); didSet = true; break; case CSSValueNoCloseQuote: state.style()->setContent(NO_CLOSE_QUOTE, didSet); didSet = true; break; default: // normal and none do not have any effect. { } } } } if (!didSet) state.style()->clearContent(); }