201 if (!isPresentationAttribute(attribute->name()))
202 continue;
203 if (!attribute->namespaceURI().isNull())
204 return;
205 // FIXME: Background URL may depend on the base URL and can't be shared. Disallow caching.
206 if (attribute->name() == backgroundAttr)
207 return;
208 result.attributesAndValues.append(make_pair(attribute->localName().impl(), attribute->value()));
209 }
210 if (result.attributesAndValues.isEmpty())
211 return;
212 // Attribute order doesn't matter. Sort for easy equality comparison.
213 std::sort(result.attributesAndValues.begin(), result.attributesAndValues.end(), attributeNameSort);
214 // The cache key is non-null when the tagName is set.
215 result.tagName = localName().impl();
216}
217
218static unsigned computePresentationAttributeCacheHash(const PresentationAttributeCacheKey& key)
219{
220 if (!key.tagName)
221 return 0;
222 ASSERT(key.attributesAndValues.size());
223 unsigned attributeHash = StringHasher::hashMemory(key.attributesAndValues.data(), key.attributesAndValues.size() * sizeof(key.attributesAndValues[0]));
224 return WTF::intHash((static_cast<uint64_t>(key.tagName->existingHash()) << 32 | attributeHash));
225}
226
227void StyledElement::updateAttributeStyle()
228{
229 PresentationAttributeCacheKey cacheKey;
230 makePresentationAttributeCacheKey(cacheKey);
231
232 unsigned cacheHash = computePresentationAttributeCacheHash(cacheKey);
233
234 PresentationAttributeCache::iterator cacheIterator;
235 if (cacheHash) {
236 cacheIterator = presentationAttributeCache().add(cacheHash, nullptr).first;
237 if (cacheIterator->second && cacheIterator->second->key != cacheKey)
238 cacheHash = 0;
239 }
240
241 RefPtr<StylePropertySet> style;
242 if (cacheHash && cacheIterator->second)
243 style = cacheIterator->second->value;
244 else {
245 style = StylePropertySet::create();
246 unsigned size = attributeCount();
247 for (unsigned i = 0; i < size; ++i) {
248 Attribute* attribute = attributeItem(i);
249 collectStyleForAttribute(attribute, style.get());
250 }