CSSImageSetValue.cpp [plain text]
#include "config.h"
#include "CSSImageSetValue.h"
#include "CSSImageGeneratorValue.h"
#include "CSSImageValue.h"
#include "CSSPrimitiveValue.h"
#include "Document.h"
#include "Page.h"
#include "StyleBuilderState.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
Ref<CSSImageSetValue> CSSImageSetValue::create()
{
return adoptRef(*new CSSImageSetValue);
}
CSSImageSetValue::CSSImageSetValue()
: CSSValueList(ImageSetClass, CommaSeparator)
{
}
CSSImageSetValue::~CSSImageSetValue() = default;
void CSSImageSetValue::fillImageSet()
{
size_t length = this->length();
for (size_t i = 0; i + 1 < length; i += 2) {
CSSValue* imageValue = item(i);
CSSValue* scaleFactorValue = item(i + 1);
ASSERT(is<CSSImageValue>(imageValue) || is<CSSImageGeneratorValue>(imageValue));
ASSERT(is<CSSPrimitiveValue>(scaleFactorValue));
float scaleFactor = downcast<CSSPrimitiveValue>(scaleFactorValue)->floatValue(CSSUnitType::CSS_DPPX);
m_imagesInSet.append({ imageValue, scaleFactor });
}
std::stable_sort(m_imagesInSet.begin(), m_imagesInSet.end(), CSSImageSetValue::compareByScaleFactor);
}
ImageWithScale CSSImageSetValue::bestImageForScaleFactor()
{
if (!m_imagesInSet.size())
fillImageSet();
ImageWithScale image;
size_t numberOfImages = m_imagesInSet.size();
for (size_t i = 0; i < numberOfImages; ++i) {
image = m_imagesInSet.at(i);
if (image.scaleFactor >= m_deviceScaleFactor)
return image;
}
return image;
}
CachedImage* CSSImageSetValue::cachedImage() const
{
if (is<CSSImageValue>(m_selectedImageValue))
return downcast<CSSImageValue>(*m_selectedImageValue).cachedImage();
return nullptr;
}
ImageWithScale CSSImageSetValue::selectBestFitImage(const Document& document)
{
updateDeviceScaleFactor(document);
if (!m_accessedBestFitImage) {
m_accessedBestFitImage = true;
m_bestFitImage = bestImageForScaleFactor();
}
return m_bestFitImage;
}
void CSSImageSetValue::updateDeviceScaleFactor(const Document& document)
{
float deviceScaleFactor = document.page() ? document.page()->deviceScaleFactor() : 1;
if (deviceScaleFactor == m_deviceScaleFactor)
return;
m_deviceScaleFactor = deviceScaleFactor;
m_accessedBestFitImage = false;
m_selectedImageValue = nullptr;
}
Ref<CSSImageSetValue> CSSImageSetValue::imageSetWithStylesResolved(Style::BuilderState& builderState)
{
Ref<CSSImageSetValue> result = CSSImageSetValue::create();
size_t length = this->length();
for (size_t i = 0; i + 1 < length; i += 2) {
result->append(builderState.resolveImageStyles(*itemWithoutBoundsCheck(i)));
result->append(*itemWithoutBoundsCheck(i + 1));
}
return result;
}
String CSSImageSetValue::customCSSText() const
{
StringBuilder result;
result.appendLiteral("image-set(");
size_t length = this->length();
for (size_t i = 0; i + 1 < length; i += 2) {
if (i > 0)
result.appendLiteral(", ");
result.append(item(i)->cssText(), ' ', item(i + 1)->cssText());
}
result.append(')');
return result.toString();
}
bool CSSImageSetValue::traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const
{
return m_selectedImageValue && m_selectedImageValue->traverseSubresources(handler);
}
}