Diff
Modified: trunk/LayoutTests/ChangeLog (290177 => 290178)
--- trunk/LayoutTests/ChangeLog 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/LayoutTests/ChangeLog 2022-02-18 23:50:27 UTC (rev 290178)
@@ -1,3 +1,15 @@
+2022-02-18 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Live Text] Add a mechanism to inject images into image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=236842
+
+ Reviewed by Aditya Keerthi.
+
+ Add a layout test that exercises the new cropped image overlay code.
+
+ * fast/images/text-recognition/image-overlay-cropped-image-expected.txt: Added.
+ * fast/images/text-recognition/image-overlay-cropped-image.html: Added.
+
2022-02-18 Kimmo Kinnunen <kkinnu...@apple.com>
WebGL GPUP: Crash when running fast/mediastream/getUserMedia-to-canvas-1.html
Added: trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image-expected.txt (0 => 290178)
--- trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image-expected.txt 2022-02-18 23:50:27 UTC (rev 290178)
@@ -0,0 +1,13 @@
+
+PASS croppedImage is non-null.
+PASS croppedImageBackdrop is non-null.
+PASS croppedImageRect.x is 100
+PASS croppedImageRect.y is 100
+PASS croppedImageRect.width is 200
+PASS croppedImageRect.height is 200
+PASS croppedImage is null
+PASS croppedImageBackdrop is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image.html (0 => 290178)
--- trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image.html (rev 0)
+++ trunk/LayoutTests/fast/images/text-recognition/image-overlay-cropped-image.html 2022-02-18 23:50:27 UTC (rev 290178)
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+body, html {
+ margin: 0;
+}
+</style>
+</head>
+<body>
+<img src=""
+<pre id="console"></pre>
+<script>
+addEventListener("load", () => {
+ const image = document.querySelector("img");
+
+ internals.installCroppedImageOverlay(image, new DOMRectReadOnly(0.25, 0.25, 0.5, 0.5));
+
+ croppedImage = internals.shadowRoot(image).getElementById("image-overlay-cropped-image");
+ croppedImageBackdrop = internals.shadowRoot(image).getElementById("image-overlay-cropped-image-backdrop");
+ shouldBeNonNull("croppedImage");
+ shouldBeNonNull("croppedImageBackdrop");
+
+ croppedImageRect = croppedImage.getBoundingClientRect();
+ shouldBe("croppedImageRect.x", "100");
+ shouldBe("croppedImageRect.y", "100");
+ shouldBe("croppedImageRect.width", "200");
+ shouldBe("croppedImageRect.height", "200");
+
+ internals.uninstallCroppedImageOverlay();
+
+ croppedImage = internals.shadowRoot(image).getElementById("image-overlay-cropped-image");
+ croppedImageBackdrop = internals.shadowRoot(image).getElementById("image-overlay-cropped-image-backdrop");
+ shouldBeNull("croppedImage");
+ shouldBeNull("croppedImageBackdrop");
+});
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (290177 => 290178)
--- trunk/Source/WebCore/ChangeLog 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/ChangeLog 2022-02-18 23:50:27 UTC (rev 290178)
@@ -1,3 +1,68 @@
+2022-02-18 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Live Text] Add a mechanism to inject images into image overlays
+ https://bugs.webkit.org/show_bug.cgi?id=236842
+
+ Reviewed by Aditya Keerthi.
+
+ To support additional behaviors around the "Copy Cropped Image" context menu item on macOS, add a new image
+ overlay helper method to install a temporary image element within the image overlay shadow root of a host image.
+ See below for more details.
+
+ Test: fast/images/text-recognition/image-overlay-cropped-image.html
+
+ * dom/ImageOverlay.cpp:
+ (WebCore::ImageOverlay::imageOverlayCroppedImageIdentifier):
+ (WebCore::ImageOverlay::imageOverlayCroppedImageBackdropIdentifier):
+ (WebCore::ImageOverlay::isOverlayText):
+ (WebCore::ImageOverlay::removeOverlaySoonIfNeeded):
+ (WebCore::ImageOverlay::installImageOverlayStyleSheet):
+
+ Pull out logic for installing the UA style sheet for image overlays into a helper method, so that we can ensure
+ the stylesheet in both cases where the `CroppedImage` is installed first, or Live Text is injected first.
+
+ (WebCore::ImageOverlay::updateSubtree):
+
+ Refactor this method to not completely remove the image overlay root container in the case where the Live Text
+ subtree needs to be regenerated; this prevents us from inadvertently removing the cropped image overlay elements
+ when updating Live Text elements in the UA shadow root.
+
+ (WebCore::ImageOverlay::CroppedImage::install):
+
+ Add a method to install a cropped image overlay into the given host element. This creates a new blob URL using
+ the given image data and MIME type, and uses it to insert an image element within the image overlay root
+ container that's absolutely positioned over the given crop rect (normalized relative to the image).
+
+ This inserted image is presented over another dimming element that fades in and out as `setVisibility()` is
+ called. Finally, `install` returns a `unique_ptr` to a RAII object that can be used to fade the cropped image
+ backdrop in or out; when destroyed, this RAII object immediately disconnects both the backdrop and the image
+ element, and revokes the temporary blob URL created during `install()`.
+
+ (WebCore::ImageOverlay::CroppedImage::CroppedImage):
+ (WebCore::ImageOverlay::CroppedImage::~CroppedImage):
+ (WebCore::ImageOverlay::CroppedImage::setVisibility):
+ * dom/ImageOverlay.h:
+ * dom/ShadowRoot.h:
+
+ Add a `using TreeScope::getElementById;` here to make it possible to call `getElementById` on `ShadowRoot`
+ without having to cast to a `TreeScope`.
+
+ * html/shadow/imageOverlay.css:
+ (img#image-overlay-cropped-image):
+ (div#image-overlay-cropped-image-backdrop):
+ * testing/Internals.cpp:
+ (WebCore::Internals::pngDataForTesting):
+ (WebCore::Internals::installCroppedImageOverlay):
+ (WebCore::Internals::uninstallCroppedImageOverlay):
+
+ Add internal testing support for the cropped image overlay by allowing layout tests to inject an image overlay
+ with hard-coded PNG data into the given element.
+
+ * testing/Internals.h:
+ * testing/Internals.idl:
+ * testing/Internals.mm:
+ (WebCore::Internals::pngDataForTesting):
+
2022-02-18 Kimmo Kinnunen <kkinnu...@apple.com>
WebGL GPUP: Crash when running fast/mediastream/getUserMedia-to-canvas-1.html
Modified: trunk/Source/WebCore/dom/ImageOverlay.cpp (290177 => 290178)
--- trunk/Source/WebCore/dom/ImageOverlay.cpp 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/dom/ImageOverlay.cpp 2022-02-18 23:50:27 UTC (rev 290178)
@@ -26,16 +26,20 @@
#include "config.h"
#include "ImageOverlay.h"
+#include "Blob.h"
#include "CharacterRange.h"
#include "DOMTokenList.h"
+#include "DOMURL.h"
#include "Document.h"
#include "ElementChildIterator.h"
#include "EventHandler.h"
#include "EventLoop.h"
+#include "FloatRect.h"
#include "FloatSize.h"
#include "GeometryUtilities.h"
#include "HTMLBRElement.h"
#include "HTMLDivElement.h"
+#include "HTMLImageElement.h"
#include "HTMLMediaElement.h"
#include "HTMLStyleElement.h"
#include "ImageOverlayController.h"
@@ -45,6 +49,7 @@
#include "RenderImage.h"
#include "RenderText.h"
#include "ShadowRoot.h"
+#include "SharedBuffer.h"
#include "SimpleRange.h"
#include "Text.h"
#include "TextIterator.h"
@@ -96,6 +101,18 @@
#endif // ENABLE(IMAGE_ANALYSIS)
+static const AtomString& imageOverlayCroppedImageIdentifier()
+{
+ static MainThreadNeverDestroyed<const AtomString> identifier("image-overlay-cropped-image", AtomString::ConstructFromLiteral);
+ return identifier;
+}
+
+static const AtomString& imageOverlayCroppedImageBackdropIdentifier()
+{
+ static MainThreadNeverDestroyed<const AtomString> identifier("image-overlay-cropped-image-backdrop", AtomString::ConstructFromLiteral);
+ return identifier;
+}
+
bool hasOverlay(const HTMLElement& element)
{
auto shadowRoot = element.shadowRoot();
@@ -178,7 +195,7 @@
if (!host)
return false;
- if (RefPtr overlay = static_cast<TreeScope&>(*host->userAgentShadowRoot()).getElementById(imageOverlayElementIdentifier()))
+ if (RefPtr overlay = host->userAgentShadowRoot()->getElementById(imageOverlayElementIdentifier()))
return node.isDescendantOf(*overlay);
return false;
@@ -198,7 +215,7 @@
if (!shadowRoot)
return;
- if (RefPtr overlay = static_cast<TreeScope&>(*shadowRoot).getElementById(imageOverlayElementIdentifier()))
+ if (RefPtr overlay = shadowRoot->getElementById(imageOverlayElementIdentifier()))
overlay->remove();
#if ENABLE(IMAGE_ANALYSIS)
@@ -208,7 +225,13 @@
});
}
-#if ENABLE(IMAGE_ANALYSIS)
+static void installImageOverlayStyleSheet(ShadowRoot& shadowRoot)
+{
+ static MainThreadNeverDestroyed<const String> shadowStyle(StringImpl::createWithoutCopying(imageOverlayUserAgentStyleSheet, sizeof(imageOverlayUserAgentStyleSheet)));
+ auto style = HTMLStyleElement::create(HTMLNames::styleTag, shadowRoot.document(), false);
+ style->setTextContent(shadowStyle);
+ shadowRoot.appendChild(WTFMove(style));
+}
IntRect containerRect(HTMLElement& element)
{
@@ -222,6 +245,8 @@
return enclosingIntRect(downcast<RenderImage>(*renderer).replacedContentRect());
}
+#if ENABLE(IMAGE_ANALYSIS)
+
struct LineElements {
Ref<HTMLDivElement> line;
Vector<Ref<HTMLElement>> children;
@@ -280,6 +305,7 @@
}
}
+ bool canUseExistingElements = false;
if (elements.root) {
for (auto& childElement : childrenOfType<HTMLDivElement>(*elements.root)) {
if (!childElement.hasClass())
@@ -303,7 +329,7 @@
elements.lines.append({ childElement, WTFMove(lineChildren), childrenOfType<HTMLBRElement>(childElement).first() });
}
- bool canUseExistingElements = ([&] {
+ canUseExistingElements = ([&] {
if (result.dataDetectors.size() != elements.dataDetectors.size())
return false;
@@ -340,8 +366,8 @@
})();
if (!canUseExistingElements) {
- elements.root->remove();
- elements = { };
+ elements.root->removeChildren();
+ elements = { elements.root, { }, { }, { } };
}
}
@@ -350,23 +376,25 @@
Ref document = element.document();
Ref shadowRoot = element.ensureUserAgentShadowRoot();
- if (!elements.root) {
- auto rootContainer = HTMLDivElement::create(document.get());
- rootContainer->setIdAttribute(imageOverlayElementIdentifier());
- rootContainer->setTranslate(false);
- if (document->isImageDocument())
- rootContainer->setInlineStyleProperty(CSSPropertyWebkitUserSelect, CSSValueText);
+ if (!canUseExistingElements) {
+ if (!elements.root) {
+ auto rootContainer = HTMLDivElement::create(document.get());
+ rootContainer->setIdAttribute(imageOverlayElementIdentifier());
+ rootContainer->setTranslate(false);
+ if (document->isImageDocument())
+ rootContainer->setInlineStyleProperty(CSSPropertyWebkitUserSelect, CSSValueText);
- if (mediaControlsContainer)
- mediaControlsContainer->appendChild(rootContainer);
- else
- shadowRoot->appendChild(rootContainer);
- elements.root = rootContainer.copyRef();
+ if (mediaControlsContainer)
+ mediaControlsContainer->appendChild(rootContainer);
+ else
+ shadowRoot->appendChild(rootContainer);
+ elements.root = rootContainer.copyRef();
+ }
elements.lines.reserveInitialCapacity(result.lines.size());
for (auto& line : result.lines) {
auto lineContainer = HTMLDivElement::create(document.get());
lineContainer->classList().add(imageOverlayLineClass());
- rootContainer->appendChild(lineContainer);
+ elements.root->appendChild(lineContainer);
LineElements lineElements { lineContainer, { }, { } };
lineElements.children.reserveInitialCapacity(line.children.size());
for (size_t childIndex = 0; childIndex < line.children.size(); ++childIndex) {
@@ -391,7 +419,7 @@
for (auto& dataDetector : result.dataDetectors) {
auto dataDetectorContainer = DataDetection::createElementForImageOverlay(document.get(), dataDetector);
dataDetectorContainer->classList().add(imageOverlayDataDetectorClass());
- rootContainer->appendChild(dataDetectorContainer);
+ elements.root->appendChild(dataDetectorContainer);
elements.dataDetectors.uncheckedAppend(WTFMove(dataDetectorContainer));
}
#endif // ENABLE(DATA_DETECTION)
@@ -400,7 +428,7 @@
for (auto& block : result.blocks) {
auto blockContainer = HTMLDivElement::create(document.get());
blockContainer->classList().add(imageOverlayBlockClass());
- rootContainer->appendChild(blockContainer);
+ elements.root->appendChild(blockContainer);
blockContainer->appendChild(Text::create(document.get(), makeString('\n', block.text)));
elements.blocks.uncheckedAppend(WTFMove(blockContainer));
}
@@ -411,12 +439,8 @@
}
}
- if (!hadExistingElements) {
- static MainThreadNeverDestroyed<const String> shadowStyle(StringImpl::createWithoutCopying(imageOverlayUserAgentStyleSheet, sizeof(imageOverlayUserAgentStyleSheet)));
- auto style = HTMLStyleElement::create(HTMLNames::styleTag, document.get(), false);
- style->setTextContent(shadowStyle);
- shadowRoot->appendChild(WTFMove(style));
- }
+ if (!hadExistingElements)
+ installImageOverlayStyleSheet(shadowRoot.get());
return elements;
}
@@ -649,5 +673,87 @@
#endif // ENABLE(IMAGE_ANALYSIS)
+std::unique_ptr<CroppedImage> CroppedImage::install(HTMLElement& host, Ref<SharedBuffer>&& imageData, const String& mimeType, FloatRect normalizedRect)
+{
+ Ref document = host.document();
+ Ref shadowRoot = host.ensureUserAgentShadowRoot();
+ RefPtr imageOverlayRoot = dynamicDowncast<HTMLDivElement>(shadowRoot->getElementById(imageOverlayElementIdentifier()));
+ if (!imageOverlayRoot) {
+ imageOverlayRoot = HTMLDivElement::create(document.get());
+ imageOverlayRoot->setIdAttribute(imageOverlayElementIdentifier());
+ imageOverlayRoot->setTranslate(false);
+ shadowRoot->appendChild(*imageOverlayRoot);
+ installImageOverlayStyleSheet(shadowRoot.get());
+ }
+
+ document->updateLayoutIgnorePendingStylesheets();
+
+ if (auto* renderer = dynamicDowncast<RenderImage>(host.renderer()))
+ renderer->setHasImageOverlay();
+
+ auto containerRect = ImageOverlay::containerRect(host);
+ auto cropRect = normalizedRect;
+ cropRect.scale(containerRect.width(), containerRect.height());
+ cropRect.move(containerRect.x(), containerRect.y());
+
+ auto croppedImageBackdrop = HTMLDivElement::create(document.get());
+ croppedImageBackdrop->setIdAttribute(imageOverlayCroppedImageBackdropIdentifier());
+ imageOverlayRoot->appendChild(croppedImageBackdrop.get());
+
+ auto croppedImage = HTMLImageElement::create(document.get());
+ auto croppedImageURL = DOMURL::createObjectURL(document.get(), Blob::create(document.ptr(), imageData->extractData(), mimeType));
+ croppedImage->setIdAttribute(imageOverlayCroppedImageIdentifier());
+ croppedImage->setAttributeWithoutSynchronization(HTMLNames::srcAttr, croppedImageURL);
+ croppedImage->setInlineStyleProperty(CSSPropertyLeft, cropRect.x(), CSSUnitType::CSS_PX);
+ croppedImage->setInlineStyleProperty(CSSPropertyTop, cropRect.y(), CSSUnitType::CSS_PX);
+ croppedImage->setInlineStyleProperty(CSSPropertyWidth, cropRect.width(), CSSUnitType::CSS_PX);
+ croppedImage->setInlineStyleProperty(CSSPropertyHeight, cropRect.height(), CSSUnitType::CSS_PX);
+ imageOverlayRoot->appendChild(croppedImage.get());
+
+ document->updateLayoutIgnorePendingStylesheets();
+ croppedImageBackdrop->setInlineStyleProperty(CSSPropertyOpacity, 0.5, CSSUnitType::CSS_NUMBER);
+
+ return makeUnique<CroppedImage>(document.get(), host, croppedImageBackdrop.get(), croppedImageURL);
+}
+
+CroppedImage::CroppedImage(Document& document, HTMLElement& host, HTMLElement& croppedImageBackdrop, const String& imageURL)
+ : m_document(document)
+ , m_host(host)
+ , m_croppedImageBackdrop(croppedImageBackdrop)
+ , m_imageURL(imageURL)
+{
+ setVisibility(true);
+}
+
+CroppedImage::~CroppedImage()
+{
+ if (RefPtr document = m_document.get())
+ DOMURL::revokeObjectURL(*document, m_imageURL);
+
+ RefPtr host = m_host.get();
+ if (!host)
+ return;
+
+ RefPtr shadowRoot = host->shadowRoot();
+ if (!shadowRoot || shadowRoot->mode() != ShadowRootMode::UserAgent)
+ return;
+
+ if (RefPtr croppedImage = shadowRoot->getElementById(imageOverlayCroppedImageIdentifier()))
+ croppedImage->remove();
+
+ if (RefPtr croppedImageBackdrop = shadowRoot->getElementById(imageOverlayCroppedImageBackdropIdentifier()))
+ croppedImageBackdrop->remove();
+}
+
+void CroppedImage::setVisibility(bool visible)
+{
+ RefPtr croppedImageBackdrop = m_croppedImageBackdrop.get();
+ if (!croppedImageBackdrop)
+ return;
+
+ croppedImageBackdrop->document().updateLayoutIgnorePendingStylesheets();
+ croppedImageBackdrop->setInlineStyleProperty(CSSPropertyOpacity, visible ? 0.5 : 0, CSSUnitType::CSS_NUMBER);
+}
+
} // namespace ImageOverlay
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/ImageOverlay.h (290177 => 290178)
--- trunk/Source/WebCore/dom/ImageOverlay.h 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/dom/ImageOverlay.h 2022-02-18 23:50:27 UTC (rev 290178)
@@ -26,11 +26,15 @@
#pragma once
#include "IntRect.h"
+#include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
namespace WebCore {
+class FloatRect;
class HTMLElement;
class Node;
+class SharedBuffer;
class VisibleSelection;
struct CharacterRange;
@@ -55,6 +59,24 @@
WEBCORE_EXPORT void updateWithTextRecognitionResult(HTMLElement&, const TextRecognitionResult&, CacheTextRecognitionResults = CacheTextRecognitionResults::Yes);
#endif
+class CroppedImage {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(CroppedImage);
+public:
+ WEBCORE_EXPORT static std::unique_ptr<CroppedImage> install(HTMLElement&, Ref<SharedBuffer>&&, const String&, FloatRect);
+
+ CroppedImage(Document&, HTMLElement&, HTMLElement&, const String& imageURL);
+ WEBCORE_EXPORT ~CroppedImage();
+
+ WEBCORE_EXPORT void setVisibility(bool);
+
+private:
+ WeakPtr<Document> m_document;
+ WeakPtr<HTMLElement> m_host;
+ WeakPtr<HTMLElement> m_croppedImageBackdrop;
+ String m_imageURL;
+};
+
} // namespace ImageOverlay
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/ShadowRoot.h (290177 => 290178)
--- trunk/Source/WebCore/dom/ShadowRoot.h 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/dom/ShadowRoot.h 2022-02-18 23:50:27 UTC (rev 290178)
@@ -61,6 +61,7 @@
virtual ~ShadowRoot();
+ using TreeScope::getElementById;
using TreeScope::rootNode;
WEBCORE_EXPORT Style::Scope& styleScope();
Modified: trunk/Source/WebCore/html/shadow/imageOverlay.css (290177 => 290178)
--- trunk/Source/WebCore/html/shadow/imageOverlay.css 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/html/shadow/imageOverlay.css 2022-02-18 23:50:27 UTC (rev 290178)
@@ -71,3 +71,18 @@
position: absolute;
-webkit-user-select: none;
}
+
+img#image-overlay-cropped-image {
+ position: absolute;
+ pointer-events: none;
+}
+
+div#image-overlay-cropped-image-backdrop {
+ position: absolute;
+ background: white;
+ width: 100%;
+ height: 100%;
+ transition: opacity 0.5s ease-in-out;
+ opacity: 0;
+ pointer-events: none;
+}
Modified: trunk/Source/WebCore/testing/Internals.cpp (290177 => 290178)
--- trunk/Source/WebCore/testing/Internals.cpp 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/testing/Internals.cpp 2022-02-18 23:50:27 UTC (rev 290178)
@@ -5134,8 +5134,13 @@
}
#endif
-#endif
+RefPtr<SharedBuffer> Internals::pngDataForTesting()
+{
+ return nullptr;
+}
+#endif // !PLATFORM(COCOA)
+
#if ENABLE(VIDEO)
bool Internals::isMediaElementHidden(const HTMLMediaElement& media)
{
@@ -5879,6 +5884,29 @@
#endif
}
+void Internals::installCroppedImageOverlay(Element& element, Ref<DOMRectReadOnly>&& normalizedCropRect)
+{
+ RefPtr htmlElement = dynamicDowncast<HTMLElement>(element);
+ if (!htmlElement)
+ return;
+
+ auto imageData = pngDataForTesting();
+ if (!imageData)
+ return;
+
+ m_croppedImageOverlay = ImageOverlay::CroppedImage::install(*htmlElement, imageData.releaseNonNull(), "image/png"_s, {
+ static_cast<float>(normalizedCropRect->x()),
+ static_cast<float>(normalizedCropRect->y()),
+ static_cast<float>(normalizedCropRect->width()),
+ static_cast<float>(normalizedCropRect->height())
+ });
+}
+
+void Internals::uninstallCroppedImageOverlay()
+{
+ m_croppedImageOverlay = nullptr;
+}
+
bool Internals::hasActiveDataDetectorHighlight() const
{
#if ENABLE(DATA_DETECTION) && ENABLE(IMAGE_ANALYSIS)
Modified: trunk/Source/WebCore/testing/Internals.h (290177 => 290178)
--- trunk/Source/WebCore/testing/Internals.h 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/testing/Internals.h 2022-02-18 23:50:27 UTC (rev 290178)
@@ -106,6 +106,7 @@
class SVGSVGElement;
class ScrollableArea;
class SerializedScriptValue;
+class SharedBuffer;
class SourceBuffer;
class StringCallback;
class StyleSheet;
@@ -151,6 +152,10 @@
#endif
#endif
+namespace ImageOverlay {
+class CroppedImage;
+}
+
template<typename IDLType> class DOMPromiseDeferred;
struct MockWebAuthenticationConfiguration;
@@ -950,6 +955,8 @@
};
void installImageOverlay(Element&, Vector<ImageOverlayLine>&&, Vector<ImageOverlayBlock>&& = { }, Vector<ImageOverlayDataDetector>&& = { });
+ void installCroppedImageOverlay(Element&, Ref<DOMRectReadOnly>&&);
+ void uninstallCroppedImageOverlay();
bool hasActiveDataDetectorHighlight() const;
#if ENABLE(IMAGE_ANALYSIS)
@@ -1275,6 +1282,8 @@
static DDScannerResult *fakeDataDetectorResultForTesting();
#endif
+ static RefPtr<SharedBuffer> pngDataForTesting();
+
#if ENABLE(MEDIA_STREAM)
// RealtimeMediaSource::Observer API
void videoSampleAvailable(MediaSample&, VideoSampleMetadata) final;
@@ -1308,6 +1317,8 @@
#if ENABLE(VIDEO)
std::unique_ptr<CaptionUserPreferencesTestingModeToken> m_testingModeToken;
#endif
+
+ std::unique_ptr<ImageOverlay::CroppedImage> m_croppedImageOverlay;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/testing/Internals.idl (290177 => 290178)
--- trunk/Source/WebCore/testing/Internals.idl 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/testing/Internals.idl 2022-02-18 23:50:27 UTC (rev 290178)
@@ -978,6 +978,8 @@
[Conditional=IMAGE_ANALYSIS] readonly attribute Element? textRecognitionCandidate;
[Conditional=IMAGE_ANALYSIS] undefined requestTextRecognition(Element element, VoidCallback callback);
undefined installImageOverlay(Element element, sequence<ImageOverlayLine> lines, optional sequence<ImageOverlayBlock> blocks = [], optional sequence<ImageOverlayDataDetector> dataDetectors = []);
+ undefined installCroppedImageOverlay(Element element, DOMRectReadOnly normalizedCropRect);
+ undefined uninstallCroppedImageOverlay();
readonly attribute boolean hasActiveDataDetectorHighlight;
boolean usingAppleInternalSDK();
Modified: trunk/Source/WebCore/testing/Internals.mm (290177 => 290178)
--- trunk/Source/WebCore/testing/Internals.mm 2022-02-18 23:42:31 UTC (rev 290177)
+++ trunk/Source/WebCore/testing/Internals.mm 2022-02-18 23:50:27 UTC (rev 290178)
@@ -35,6 +35,7 @@
#import "HitTestResult.h"
#import "MediaPlayerPrivate.h"
#import "Range.h"
+#import "SharedBuffer.h"
#import "SimpleRange.h"
#import "UTIUtilities.h"
#import <AVFoundation/AVPlayer.h>
@@ -197,4 +198,10 @@
#endif // ENABLE(DATA_DETECTION)
+RefPtr<SharedBuffer> Internals::pngDataForTesting()
+{
+ NSBundle *webCoreBundle = [NSBundle bundleForClass:NSClassFromString(@"WebCoreBundleFinder")];
+ return SharedBuffer::createWithContentsOfFile([webCoreBundle pathForResource:@"missingImage" ofType:@"png"]);
}
+
+} // namespace WebCore