1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/*
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2003, 2005-2008, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2020 Noam Rosenthal (noam@webkit.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include "StyleCursorImage.h"
#include "CSSCursorImageValue.h"
#include "CSSImageValue.h"
#include "CSSValuePair.h"
#include "CachedImage.h"
#include "FloatSize.h"
#include "RenderElement.h"
#include "SVGCursorElement.h"
#include "SVGElementTypeHelpers.h"
#include "SVGLengthContext.h"
#include "SVGURIReference.h"
#include "StyleBuilderState.h"
#include "StyleCachedImage.h"
#include "StyleImageSet.h"
#include <wtf/TZoneMallocInlines.h>
namespace WebCore {
WTF_MAKE_TZONE_ALLOCATED_IMPL(StyleCursorImage);
Ref<StyleCursorImage> StyleCursorImage::create(Ref<StyleImage>&& image, const std::optional<IntPoint>& hotSpot, const URL& originalURL, LoadedFromOpaqueSource loadedFromOpaqueSource)
{
return adoptRef(*new StyleCursorImage(WTFMove(image), hotSpot, originalURL, loadedFromOpaqueSource));
}
StyleCursorImage::StyleCursorImage(Ref<StyleImage>&& image, const std::optional<IntPoint>& hotSpot, const URL& originalURL, LoadedFromOpaqueSource loadedFromOpaqueSource)
: StyleMultiImage { Type::CursorImage }
, m_image { WTFMove(image) }
, m_hotSpot { hotSpot }
, m_originalURL { originalURL }
, m_loadedFromOpaqueSource { loadedFromOpaqueSource }
{
}
StyleCursorImage::~StyleCursorImage()
{
for (auto& element : m_cursorElements)
element.removeClient(*this);
}
bool StyleCursorImage::operator==(const StyleImage& other) const
{
auto* otherCursorImage = dynamicDowncast<StyleCursorImage>(other);
return otherCursorImage && equals(*otherCursorImage);
}
bool StyleCursorImage::equals(const StyleCursorImage& other) const
{
return equalInputImages(other) && StyleMultiImage::equals(other);
}
bool StyleCursorImage::equalInputImages(const StyleCursorImage& other) const
{
return m_image.get() == other.m_image.get();
}
Ref<CSSValue> StyleCursorImage::computedStyleValue(const RenderStyle& style) const
{
RefPtr<CSSValuePair> hotSpot;
if (m_hotSpot)
hotSpot = CSSValuePair::createNoncoalescing(CSSPrimitiveValue::create(m_hotSpot->x()), CSSPrimitiveValue::create(m_hotSpot->y()));
return CSSCursorImageValue::create(m_image->computedStyleValue(style), WTFMove(hotSpot), m_originalURL, m_loadedFromOpaqueSource );
}
ImageWithScale StyleCursorImage::selectBestFitImage(const Document& document)
{
if (RefPtr imageSet = dynamicDowncast<StyleImageSet>(m_image.get()))
return imageSet->selectBestFitImage(document);
if (RefPtr cachedImage = dynamicDowncast<StyleCachedImage>(m_image.get())) {
if (RefPtr cursorElement = updateCursorElement(document)) {
auto existingImageURL = cachedImage->imageURL();
auto updatedImageURL = document.completeURL(cursorElement->href());
if (existingImageURL != updatedImageURL)
m_image = StyleCachedImage::create(CSSImageValue::create(WTFMove(updatedImageURL), m_loadedFromOpaqueSource));
}
}
return { m_image.ptr(), 1, String() };
}
RefPtr<SVGCursorElement> StyleCursorImage::updateCursorElement(const Document& document)
{
RefPtr cursorElement = dynamicDowncast<SVGCursorElement>(SVGURIReference::targetElementFromIRIString(m_originalURL.string(), document).element);
if (!cursorElement)
return nullptr;
// FIXME: Not right to keep old cursor elements as clients. The new one should replace the old, not join it in a set.
if (m_cursorElements.add(*cursorElement).isNewEntry) {
cursorElementChanged(*cursorElement);
cursorElement->addClient(*this);
}
return cursorElement;
}
void StyleCursorImage::cursorElementRemoved(SVGCursorElement& cursorElement)
{
// FIXME: Not right to stay a client of a cursor element until the element is destroyed. We'd want to stop being a client once it's no longer a valid target, like when it's disconnected.
m_cursorElements.remove(cursorElement);
}
void StyleCursorImage::cursorElementChanged(SVGCursorElement& cursorElement)
{
// FIXME: Seems wrong that changing an old cursor element, one that that is no longer the target, changes the hot spot.
// FIXME: This will override a hot spot that was specified in CSS, which is probably incorrect.
// FIXME: Should we clamp from float to int instead of just casting here?
SVGLengthContext lengthContext(nullptr);
m_hotSpot = IntPoint {
static_cast<int>(std::round(cursorElement.x().value(lengthContext))),
static_cast<int>(std::round(cursorElement.y().value(lengthContext)))
};
// FIXME: Why doesn't this funtion check for a change to the href of the cursor element? Why would we dynamically track changes to x/y but not href?
}
void StyleCursorImage::setContainerContextForRenderer(const RenderElement& renderer, const FloatSize& containerSize, float containerZoom)
{
if (!hasCachedImage())
return;
cachedImage()->setContainerContextForClient(renderer, LayoutSize(containerSize), containerZoom, m_originalURL);
}
bool StyleCursorImage::usesDataProtocol() const
{
return m_originalURL.protocolIsData();
}
} // namespace WebCore
|