Diff
Modified: trunk/LayoutTests/ChangeLog (291816 => 291817)
--- trunk/LayoutTests/ChangeLog 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/LayoutTests/ChangeLog 2022-03-24 22:27:19 UTC (rev 291817)
@@ -1,3 +1,16 @@
+2022-03-24 Antoine Quint <grao...@webkit.org>
+
+ DOM GPUP: paintSystemPreviewBadge (AR QuickLook element badge)
+ https://bugs.webkit.org/show_bug.cgi?id=238295
+ rdar://83580608
+
+ Reviewed by Dean Jackson.
+
+ The system-preview/badge.html test now passes reliably with DOM GPUP enabled,
+ which incidentally fixes bug 236922.
+
+ * platform/ios-wk2/TestExpectations:
+
2022-03-24 Kate Cheney <katherine_che...@apple.com>
REGRESSION (Safari 15.4): Nonce from link isn't used when loading style sheet
Modified: trunk/LayoutTests/platform/ios-wk2/TestExpectations (291816 => 291817)
--- trunk/LayoutTests/platform/ios-wk2/TestExpectations 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/LayoutTests/platform/ios-wk2/TestExpectations 2022-03-24 22:27:19 UTC (rev 291817)
@@ -2250,9 +2250,6 @@
webkit.org/b/236921 imported/w3c/web-platform-tests/css/css-writing-modes/vertical-alignment-vlr-023.xht [ ImageOnlyFailure ]
webkit.org/b/236921 imported/w3c/web-platform-tests/css/css-writing-modes/vertical-alignment-vrl-022.xht [ ImageOnlyFailure ]
-# Colors are significantly different enough
-webkit.org/b/236922 system-preview/badge.html [ ImageOnlyFailure ]
-
# No/bad colored boxes
webkit.org/b/236923 fast/css/paint-order-shadow.html [ ImageOnlyFailure ]
webkit.org/b/236923 imported/blink/svg/text/obb-paintserver.html [ ImageOnlyFailure ]
Modified: trunk/Source/WebCore/ChangeLog (291816 => 291817)
--- trunk/Source/WebCore/ChangeLog 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/ChangeLog 2022-03-24 22:27:19 UTC (rev 291817)
@@ -1,3 +1,55 @@
+2022-03-24 Antoine Quint <grao...@webkit.org>
+
+ DOM GPUP: paintSystemPreviewBadge (AR QuickLook element badge)
+ https://bugs.webkit.org/show_bug.cgi?id=238295
+ rdar://83580608
+
+ Reviewed by Dean Jackson.
+
+ Add a new SystemImage subclass to deal with the ARKit badge, moving the custom drawing code under
+ RenderThemeIOS::paintSystemPreviewBadge() to ARKitBadgeSystemImage::draw().
+
+ To facilitate this, we must also have ARKitBadgeSystemImage wrap the input Image provided to
+ RenderThemeIOS::paintSystemPreviewBadge() so that the CoreImage filters are applied correctly.
+
+ Finally, we remove some use of `using namespace WebCore` in WebSpeechRecognizerTask and
+ WebSpeechRecognizerTaskMock since it caused some unified build failures.
+
+ * Headers.cmake:
+ * Modules/speech/cocoa/WebSpeechRecognizerTask.mm:
+ (-[WebSpeechRecognizerTaskImpl initWithIdentifier:locale:doMultipleRecognitions:reportInterimResults:maxAlternatives:delegateCallback:]):
+ (-[WebSpeechRecognizerTaskImpl callbackWithTranscriptions:isFinal:]):
+ (-[WebSpeechRecognizerTaskImpl sendSpeechStartIfNeeded]):
+ (-[WebSpeechRecognizerTaskImpl sendSpeechEndIfNeeded]):
+ (-[WebSpeechRecognizerTaskImpl sendEndIfNeeded]):
+ (-[WebSpeechRecognizerTaskImpl speechRecognizer:availabilityDidChange:]):
+ (-[WebSpeechRecognizerTaskImpl speechRecognitionTask:didFinishSuccessfully:]):
+ (-[WebSpeechRecognizerTask initWithIdentifier:locale:doMultipleRecognitions:reportInterimResults:maxAlternatives:delegateCallback:]):
+ * Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm:
+ (-[WebSpeechRecognizerTaskMock initWithIdentifier:locale:doMultipleRecognitions:reportInterimResults:maxAlternatives:delegateCallback:]):
+ (-[WebSpeechRecognizerTaskMock audioSamplesAvailable:]):
+ (-[WebSpeechRecognizerTaskMock abort]):
+ * Modules/system-preview/ARKitBadgeSystemImage.h: Added.
+ (WebCore::ARKitBadgeSystemImage::encode const):
+ (WebCore::ARKitBadgeSystemImage::decode):
+ (isType):
+ * Modules/system-preview/ARKitBadgeSystemImage.mm: Added.
+ (WebCore::arKitBundle):
+ (WebCore::loadARKitPDFPage):
+ (WebCore::systemPreviewLogo):
+ (WebCore::ARKitBadgeSystemImage::draw const):
+ * SourcesCocoa.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * platform/graphics/SystemImage.h:
+ * platform/graphics/displaylists/DisplayListRecorder.cpp:
+ (WebCore::DisplayList::Recorder::drawSystemImage):
+ * rendering/RenderThemeIOS.h:
+ * rendering/RenderThemeIOS.mm:
+ (WebCore::RenderThemeIOS::paintSystemPreviewBadge):
+ (WebCore::arKitBundle): Deleted.
+ (WebCore::loadARKitPDFPage): Deleted.
+ (WebCore::systemPreviewLogo): Deleted.
+
2022-03-24 Kate Cheney <katherine_che...@apple.com>
REGRESSION (Safari 15.4): Nonce from link isn't used when loading style sheet
Modified: trunk/Source/WebCore/Headers.cmake (291816 => 291817)
--- trunk/Source/WebCore/Headers.cmake 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/Headers.cmake 2022-03-24 22:27:19 UTC (rev 291817)
@@ -331,6 +331,8 @@
Modules/streams/ReadableStreamSink.h
Modules/streams/ReadableStreamSource.h
+ Modules/system-preview/ARKitBadgeSystemImage.h
+
Modules/web-locks/WebLockIdentifier.h
Modules/web-locks/WebLockManagerSnapshot.h
Modules/web-locks/WebLockMode.h
Modified: trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm (291816 => 291817)
--- trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTask.mm 2022-03-24 22:27:19 UTC (rev 291817)
@@ -37,14 +37,12 @@
// Set the maximum duration to be an hour; we can adjust this if needed.
static constexpr size_t maximumRecognitionDuration = 60 * 60;
-using namespace WebCore;
-
NS_ASSUME_NONNULL_BEGIN
@interface WebSpeechRecognizerTaskImpl : NSObject<SFSpeechRecognitionTaskDelegate, SFSpeechRecognizerDelegate> {
@private
- SpeechRecognitionConnectionClientIdentifier _identifier;
- BlockPtr<void(const SpeechRecognitionUpdate&)> _delegateCallback;
+ WebCore::SpeechRecognitionConnectionClientIdentifier _identifier;
+ BlockPtr<void(const WebCore::SpeechRecognitionUpdate&)> _delegateCallback;
bool _doMultipleRecognitions;
uint64_t _maxAlternatives;
RetainPtr<SFSpeechRecognizer> _recognizer;
@@ -55,7 +53,7 @@
bool _hasSentEnd;
}
-- (instancetype)initWithIdentifier:(SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const SpeechRecognitionUpdate&))callback;
+- (instancetype)initWithIdentifier:(WebCore::SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const WebCore::SpeechRecognitionUpdate&))callback;
- (void)callbackWithTranscriptions:(NSArray<SFTranscription *> *)transcriptions isFinal:(BOOL)isFinal;
- (void)audioSamplesAvailable:(CMSampleBufferRef)sampleBuffer;
- (void)abort;
@@ -68,7 +66,7 @@
@implementation WebSpeechRecognizerTaskImpl
-- (instancetype)initWithIdentifier:(SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const SpeechRecognitionUpdate&))callback
+- (instancetype)initWithIdentifier:(WebCore::SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const WebCore::SpeechRecognitionUpdate&))callback
{
if (!(self = [super init]))
return nil;
@@ -115,7 +113,7 @@
- (void)callbackWithTranscriptions:(NSArray<SFTranscription *> *)transcriptions isFinal:(BOOL)isFinal
{
- Vector<SpeechRecognitionAlternativeData> alternatives;
+ Vector<WebCore::SpeechRecognitionAlternativeData> alternatives;
alternatives.reserveInitialCapacity(_maxAlternatives);
for (SFTranscription* transcription in transcriptions) {
// FIXME: <rdar://73629573> get confidence of SFTranscription when possible.
@@ -124,11 +122,11 @@
double confidence = [segment confidence];
maxConfidence = maxConfidence < confidence ? confidence : maxConfidence;
}
- alternatives.uncheckedAppend(SpeechRecognitionAlternativeData { [transcription formattedString], maxConfidence });
+ alternatives.uncheckedAppend(WebCore::SpeechRecognitionAlternativeData { [transcription formattedString], maxConfidence });
if (alternatives.size() == _maxAlternatives)
break;
}
- _delegateCallback(SpeechRecognitionUpdate::createResult(_identifier, { SpeechRecognitionResultData { WTFMove(alternatives), !!isFinal } }));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::createResult(_identifier, { WebCore::SpeechRecognitionResultData { WTFMove(alternatives), !!isFinal } }));
}
- (void)audioSamplesAvailable:(CMSampleBufferRef)sampleBuffer
@@ -175,7 +173,7 @@
return;
_hasSentSpeechStart = true;
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::SpeechStart));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::SpeechStart));
}
- (void)sendSpeechEndIfNeeded
@@ -184,7 +182,7 @@
return;
_hasSentSpeechEnd = true;
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::SpeechEnd));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::SpeechEnd));
}
- (void)sendEndIfNeeded
@@ -193,7 +191,7 @@
return;
_hasSentEnd = true;
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::End));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::End));
}
#pragma mark SFSpeechRecognizerDelegate
@@ -205,8 +203,8 @@
if (available || !_task)
return;
- auto error = SpeechRecognitionError { SpeechRecognitionErrorType::ServiceNotAllowed, "Speech recognition service becomes unavailable"_s };
- _delegateCallback(SpeechRecognitionUpdate::createError(_identifier, WTFMove(error)));
+ auto error = WebCore::SpeechRecognitionError { WebCore::SpeechRecognitionErrorType::ServiceNotAllowed, "Speech recognition service becomes unavailable"_s };
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::createError(_identifier, WTFMove(error)));
}
#pragma mark SFSpeechRecognitionTaskDelegate
@@ -243,8 +241,8 @@
ASSERT(isMainThread());
if (!successfully) {
- auto error = SpeechRecognitionError { SpeechRecognitionErrorType::Aborted, task.error.localizedDescription };
- _delegateCallback(SpeechRecognitionUpdate::createError(_identifier, WTFMove(error)));
+ auto error = WebCore::SpeechRecognitionError { WebCore::SpeechRecognitionErrorType::Aborted, task.error.localizedDescription };
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::createError(_identifier, WTFMove(error)));
}
[self sendEndIfNeeded];
@@ -254,7 +252,7 @@
@implementation WebSpeechRecognizerTask
-- (instancetype)initWithIdentifier:(SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const SpeechRecognitionUpdate&))callback
+- (instancetype)initWithIdentifier:(WebCore::SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const WebCore::SpeechRecognitionUpdate&))callback
{
if (!(self = [super init]))
return nil;
Modified: trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm (291816 => 291817)
--- trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm 2022-03-24 22:27:19 UTC (rev 291817)
@@ -28,13 +28,11 @@
#if HAVE(SPEECHRECOGNIZER)
-using namespace WebCore;
-
NS_ASSUME_NONNULL_BEGIN
@implementation WebSpeechRecognizerTaskMock
-- (instancetype)initWithIdentifier:(SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const SpeechRecognitionUpdate&))callback
+- (instancetype)initWithIdentifier:(WebCore::SpeechRecognitionConnectionClientIdentifier)identifier locale:(NSString*)localeIdentifier doMultipleRecognitions:(BOOL)continuous reportInterimResults:(BOOL)interimResults maxAlternatives:(unsigned long)alternatives delegateCallback:(void(^)(const WebCore::SpeechRecognitionUpdate&))callback
{
UNUSED_PARAM(localeIdentifier);
UNUSED_PARAM(interimResults);
@@ -59,12 +57,12 @@
if (!_hasSentSpeechStart) {
_hasSentSpeechStart = true;
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::SpeechStart));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::SpeechStart));
}
// Fake some recognition results.
- SpeechRecognitionAlternativeData alternative { "Test", 1.0 };
- _delegateCallback(SpeechRecognitionUpdate::createResult(_identifier, { SpeechRecognitionResultData { { WTFMove(alternative) }, true } }));
+ WebCore::SpeechRecognitionAlternativeData alternative { "Test", 1.0 };
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::createResult(_identifier, { WebCore::SpeechRecognitionResultData { { WTFMove(alternative) }, true } }));
if (!_doMultipleRecognitions)
[self abort];
@@ -78,10 +76,10 @@
if (!_hasSentSpeechEnd && _hasSentSpeechStart) {
_hasSentSpeechEnd = true;
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::SpeechEnd));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::SpeechEnd));
}
- _delegateCallback(SpeechRecognitionUpdate::create(_identifier, SpeechRecognitionUpdateType::End));
+ _delegateCallback(WebCore::SpeechRecognitionUpdate::create(_identifier, WebCore::SpeechRecognitionUpdateType::End));
}
- (void)stop
Added: trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.h (0 => 291817)
--- trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.h (rev 0)
+++ trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.h 2022-03-24 22:27:19 UTC (rev 291817)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if USE(SYSTEM_PREVIEW)
+
+#include "NativeImage.h"
+#include "SystemImage.h"
+#include <optional>
+#include <wtf/Forward.h>
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+
+OBJC_CLASS CIContext;
+
+namespace WebCore {
+
+class WEBCORE_EXPORT ARKitBadgeSystemImage final : public SystemImage {
+public:
+ static Ref<ARKitBadgeSystemImage> create(Image& image)
+ {
+ return adoptRef(*new ARKitBadgeSystemImage(image));
+ }
+
+ static Ref<ARKitBadgeSystemImage> create(RenderingResourceIdentifier renderingResourceIdentifier, FloatSize size)
+ {
+ return adoptRef(*new ARKitBadgeSystemImage(renderingResourceIdentifier, size));
+ }
+
+ virtual ~ARKitBadgeSystemImage() = default;
+
+ void draw(GraphicsContext&, const FloatRect&) const final;
+
+ Image* image() const { return m_image.get(); }
+ void setImage(Image& image) { m_image = ℑ }
+
+ RenderingResourceIdentifier imageIdentifier() const { return m_renderingResourceIdentifier; }
+
+ template<class Encoder> void encode(Encoder&) const;
+ template<class Decoder> static std::optional<Ref<ARKitBadgeSystemImage>> decode(Decoder&);
+
+private:
+ ARKitBadgeSystemImage(Image& image)
+ : SystemImage(SystemImageType::ARKitBadge)
+ , m_image(&image)
+ , m_imageSize(image.size())
+ {
+ }
+
+ ARKitBadgeSystemImage(RenderingResourceIdentifier renderingResourceIdentifier, FloatSize size)
+ : SystemImage(SystemImageType::ARKitBadge)
+ , m_renderingResourceIdentifier(renderingResourceIdentifier)
+ , m_imageSize(size)
+ {
+ }
+
+ RefPtr<Image> m_image;
+ RenderingResourceIdentifier m_renderingResourceIdentifier;
+ FloatSize m_imageSize;
+};
+
+template<class Encoder>
+void ARKitBadgeSystemImage::encode(Encoder& encoder) const
+{
+ ASSERT(m_image);
+ ASSERT(m_image->nativeImage());
+ encoder << m_image->nativeImage()->renderingResourceIdentifier();
+ encoder << m_imageSize;
+}
+
+template<class Decoder>
+std::optional<Ref<ARKitBadgeSystemImage>> ARKitBadgeSystemImage::decode(Decoder& decoder)
+{
+ std::optional<RenderingResourceIdentifier> renderingResourceIdentifier;
+ decoder >> renderingResourceIdentifier;
+ if (!renderingResourceIdentifier)
+ return std::nullopt;
+
+ std::optional<FloatSize> imageSize;
+ decoder >> imageSize;
+ if (!imageSize)
+ return std::nullopt;
+
+ return ARKitBadgeSystemImage::create(WTFMove(*renderingResourceIdentifier), WTFMove(*imageSize));
+}
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ARKitBadgeSystemImage)
+ static bool isType(const WebCore::SystemImage& systemImage) { return systemImage.systemImageType() == WebCore::SystemImageType::ARKitBadge; }
+SPECIALIZE_TYPE_TRAITS_END()
+
+#endif // USE(SYSTEM_PREVIEW)
Added: trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.mm (0 => 291817)
--- trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.mm (rev 0)
+++ trunk/Source/WebCore/Modules/system-preview/ARKitBadgeSystemImage.mm 2022-03-24 22:27:19 UTC (rev 291817)
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "ARKitBadgeSystemImage.h"
+
+#if USE(SYSTEM_PREVIEW)
+
+#import "ColorSpaceCG.h"
+#import "FloatRect.h"
+#import "GeometryUtilities.h"
+#import "GraphicsContext.h"
+#import "IOSurface.h"
+#import <CoreGraphics/CoreGraphics.h>
+#import <CoreImage/CoreImage.h>
+#import <wtf/NeverDestroyed.h>
+#import <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+static NSBundle *arKitBundle()
+{
+ static NSBundle *arKitBundle;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ arKitBundle = []() {
+#if PLATFORM(IOS_FAMILY_SIMULATOR)
+ dlopen("/System/Library/PrivateFrameworks/AssetViewer.framework/AssetViewer", RTLD_NOW);
+ return [NSBundle bundleForClass:NSClassFromString(@"ASVThumbnailView")];
+#else
+ return [NSBundle bundleWithURL:[NSURL fileURLWithPath:@"/System/Library/PrivateFrameworks/AssetViewer.framework"]];
+#endif
+ }();
+ });
+ return arKitBundle;
+}
+
+static RetainPtr<CGPDFPageRef> loadARKitPDFPage(NSString *imageName)
+{
+ NSURL *url = "" URLForResource:imageName withExtension:@"pdf"];
+ if (!url)
+ return nullptr;
+ auto document = adoptCF(CGPDFDocumentCreateWithURL((CFURLRef)url));
+ if (!document)
+ return nullptr;
+ if (!CGPDFDocumentGetNumberOfPages(document.get()))
+ return nullptr;
+ return CGPDFDocumentGetPage(document.get(), 1);
+}
+
+static RetainPtr<CGPDFPageRef> systemPreviewLogo()
+{
+ static NeverDestroyed<RetainPtr<CGPDFPageRef>> logoPage;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ logoPage.get() = loadARKitPDFPage(@"ARKitBadge");
+ });
+ return logoPage;
+}
+
+void ARKitBadgeSystemImage::draw(GraphicsContext& graphicsContext, const FloatRect& rect) const
+{
+ auto page = systemPreviewLogo();
+ if (!page)
+ return;
+
+ static const int largeBadgeDimension = 70;
+ static const int largeBadgeOffset = 20;
+
+ static const int smallBadgeDimension = 35;
+ static const int smallBadgeOffset = 8;
+
+ static const int minimumSizeForLargeBadge = 240;
+
+ bool useSmallBadge = rect.width() < minimumSizeForLargeBadge || rect.height() < minimumSizeForLargeBadge;
+ int badgeOffset = useSmallBadge ? smallBadgeOffset : largeBadgeOffset;
+ int badgeDimension = useSmallBadge ? smallBadgeDimension : largeBadgeDimension;
+
+ int minimumDimension = badgeDimension + 2 * badgeOffset;
+ if (rect.width() < minimumDimension || rect.height() < minimumDimension)
+ return;
+
+ CGRect absoluteBadgeRect = CGRectMake(rect.x() + rect.width() - badgeDimension - badgeOffset, rect.y() + badgeOffset, badgeDimension, badgeDimension);
+ CGRect insetBadgeRect = CGRectMake(rect.width() - badgeDimension - badgeOffset, badgeOffset, badgeDimension, badgeDimension);
+ CGRect badgeRect = CGRectMake(0, 0, badgeDimension, badgeDimension);
+
+ if (!m_image || !m_image->nativeImage())
+ return;
+
+ CIImage *inputImage = [CIImage imageWithCGImage:m_image->nativeImage()->platformImage().get()];
+
+ // Create a circle to be used for the clipping path in the badge, as well as the drop shadow.
+ RetainPtr<CGPathRef> circle = adoptCF(CGPathCreateWithRoundedRect(absoluteBadgeRect, badgeDimension / 2, badgeDimension / 2, nullptr));
+
+ if (graphicsContext.paintingDisabled())
+ return;
+
+ GraphicsContextStateSaver stateSaver(graphicsContext);
+
+ CGContextRef ctx = graphicsContext.platformContext();
+ if (!ctx)
+ return;
+
+ CGContextSaveGState(ctx);
+
+ // Draw a drop shadow around the circle.
+ // Use the GraphicsContext function, because it calculates the blur radius in context space,
+ // rather than screen space.
+ constexpr auto shadowColor = Color::black.colorWithAlphaByte(26);
+ graphicsContext.setShadow(FloatSize { }, 16, shadowColor);
+
+ // The circle must have an alpha channel value of 1 for the shadow color to appear.
+ CGFloat circleColorComponents[4] = { 0, 0, 0, 1 };
+ RetainPtr<CGColorRef> circleColor = adoptCF(CGColorCreate(sRGBColorSpaceRef(), circleColorComponents));
+ CGContextSetFillColorWithColor(ctx, circleColor.get());
+
+ // Clip out the circle to only show the shadow.
+ CGContextBeginPath(ctx);
+ CGContextAddRect(ctx, rect);
+ CGContextAddPath(ctx, circle.get());
+ CGContextClosePath(ctx);
+ CGContextEOClip(ctx);
+
+ // Draw a slightly smaller circle with a shadow, otherwise we'll see a fringe of the solid
+ // black circle around the edges of the clipped path below.
+ CGContextBeginPath(ctx);
+ CGRect slightlySmallerAbsoluteBadgeRect = CGRectMake(absoluteBadgeRect.origin.x + 0.5, absoluteBadgeRect.origin.y + 0.5, badgeDimension - 1, badgeDimension - 1);
+ RetainPtr<CGPathRef> slightlySmallerCircle = adoptCF(CGPathCreateWithRoundedRect(slightlySmallerAbsoluteBadgeRect, slightlySmallerAbsoluteBadgeRect.size.width / 2, slightlySmallerAbsoluteBadgeRect.size.height / 2, nullptr));
+ CGContextAddPath(ctx, slightlySmallerCircle.get());
+ CGContextClosePath(ctx);
+ CGContextFillPath(ctx);
+
+ CGContextRestoreGState(ctx);
+
+ // Draw the blurred backdrop. Scale from intrinsic size to render size.
+ CGAffineTransform transform = CGAffineTransformIdentity;
+ transform = CGAffineTransformScale(transform, rect.width() / m_imageSize.width(), rect.height() / m_imageSize.height());
+ CIImage *scaledImage = [inputImage imageByApplyingTransform:transform];
+
+ // CoreImage coordinates are y-up, so we need to flip the badge rectangle within the image frame.
+ CGRect flippedInsetBadgeRect = CGRectMake(insetBadgeRect.origin.x, rect.height() - insetBadgeRect.origin.y - insetBadgeRect.size.height, badgeDimension, badgeDimension);
+
+ // Create a cropped region with pixel values extending outwards.
+ CIImage *clampedImage = [scaledImage imageByClampingToRect:flippedInsetBadgeRect];
+
+ // Blur.
+ CIImage *blurredImage = [clampedImage imageByApplyingGaussianBlurWithSigma:10];
+
+ // Saturate.
+ CIFilter *saturationFilter = [CIFilter filterWithName:@"CIColorControls"];
+ [saturationFilter setValue:blurredImage forKey:kCIInputImageKey];
+ [saturationFilter setValue:@1.8 forKey:kCIInputSaturationKey];
+
+ // Tint.
+ CIFilter *tintFilter1 = [CIFilter filterWithName:@"CIConstantColorGenerator"];
+ CIColor *tintColor1 = [CIColor colorWithRed:1 green:1 blue:1 alpha:0.18];
+ [tintFilter1 setValue:tintColor1 forKey:kCIInputColorKey];
+
+ // Blend the tint with the saturated output.
+ CIFilter *sourceOverFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];
+ [sourceOverFilter setValue:tintFilter1.outputImage forKey:kCIInputImageKey];
+ [sourceOverFilter setValue:saturationFilter.outputImage forKey:kCIInputBackgroundImageKey];
+
+ RetainPtr<CIContext> ciContext = [CIContext context];
+
+ RetainPtr<CGImageRef> cgImage;
+#if HAVE(IOSURFACE_COREIMAGE_SUPPORT)
+ // Crop the result to the badge location.
+ CIImage *croppedImage = [sourceOverFilter.outputImage imageByCroppingToRect:flippedInsetBadgeRect];
+ CIImage *translatedImage = [croppedImage imageByApplyingTransform:CGAffineTransformMakeTranslation(-flippedInsetBadgeRect.origin.x, -flippedInsetBadgeRect.origin.y)];
+
+ auto surfaceDimension = useSmallBadge ? smallBadgeDimension : largeBadgeDimension;
+ std::unique_ptr<IOSurface> badgeSurface = IOSurface::create({ surfaceDimension, surfaceDimension }, DestinationColorSpace::SRGB());
+ IOSurfaceRef surface = badgeSurface->surface();
+ [ciContext render:translatedImage toIOSurface:surface bounds:badgeRect colorSpace:sRGBColorSpaceRef()];
+ cgImage = useSmallBadge ? badgeSurface->createImage() : badgeSurface->createImage();
+#else
+ cgImage = adoptCF([ciContext createCGImage:sourceOverFilter.outputImage fromRect:flippedInsetBadgeRect]);
+#endif
+
+ // Before we render the result, we should clip to a circle around the badge rectangle.
+ CGContextSaveGState(ctx);
+ CGContextBeginPath(ctx);
+ CGContextAddPath(ctx, circle.get());
+ CGContextClosePath(ctx);
+ CGContextClip(ctx);
+
+ CGContextTranslateCTM(ctx, absoluteBadgeRect.origin.x, absoluteBadgeRect.origin.y);
+ CGContextTranslateCTM(ctx, 0, badgeDimension);
+ CGContextScaleCTM(ctx, 1, -1);
+ CGContextDrawImage(ctx, badgeRect, cgImage.get());
+
+ CGSize pdfSize = CGPDFPageGetBoxRect(page.get(), kCGPDFMediaBox).size;
+ CGFloat scaleX = badgeDimension / pdfSize.width;
+ CGFloat scaleY = badgeDimension / pdfSize.height;
+ CGContextScaleCTM(ctx, scaleX, scaleY);
+ CGContextDrawPDFPage(ctx, page.get());
+
+ CGContextFlush(ctx);
+ CGContextRestoreGState(ctx);
+}
+
+} // namespace WebCore
+
+#endif // USE(SYSTEM_PREVIEW)
Modified: trunk/Source/WebCore/SourcesCocoa.txt (291816 => 291817)
--- trunk/Source/WebCore/SourcesCocoa.txt 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/SourcesCocoa.txt 2022-03-24 22:27:19 UTC (rev 291817)
@@ -119,6 +119,7 @@
Modules/speech/cocoa/SpeechRecognizerCocoa.mm
Modules/speech/cocoa/WebSpeechRecognizerTask.mm
Modules/speech/cocoa/WebSpeechRecognizerTaskMock.mm
+Modules/system-preview/ARKitBadgeSystemImage.mm
Modules/webdatabase/cocoa/DatabaseManagerCocoa.mm
accessibility/ios/AXObjectCacheIOS.mm
accessibility/ios/AccessibilityObjectIOS.mm
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (291816 => 291817)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-03-24 22:27:19 UTC (rev 291817)
@@ -2310,6 +2310,7 @@
7156BCA121CA350F00534397 /* BasicEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7156BC9F21CA350600534397 /* BasicEffectTiming.h */; };
715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
+ 716C4C3627EB60C900531467 /* ARKitBadgeSystemImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 716C4C3527EB608E00531467 /* ARKitBadgeSystemImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
71729F7E20F3BB4700801CE6 /* JSDocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */; };
7173694A275E0B5E003ADA9B /* CustomEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A74B082759293600DE80BA /* CustomEffect.h */; };
@@ -11186,6 +11187,8 @@
716A55AB26FA349B00C96D69 /* range-button.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = "range-button.css"; sourceTree = "<group>"; };
716A55AD26FA349C00C96D69 /* volume-button.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "volume-button.js"; sourceTree = "<group>"; };
716A55AE26FA349C00C96D69 /* range-button.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode._javascript_; path = "range-button.js"; sourceTree = "<group>"; };
+ 716C4C3427EB608E00531467 /* ARKitBadgeSystemImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ARKitBadgeSystemImage.mm; sourceTree = "<group>"; };
+ 716C4C3527EB608E00531467 /* ARKitBadgeSystemImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARKitBadgeSystemImage.h; sourceTree = "<group>"; };
716FA0D81DB26591007323CC /* airplay-button.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = "airplay-button.css"; sourceTree = "<group>"; };
716FA0D91DB26591007323CC /* airplay-button.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "airplay-button.js"; sourceTree = "<group>"; };
716FA0DA1DB26591007323CC /* airplay-placard.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "airplay-placard.js"; sourceTree = "<group>"; };
@@ -24665,6 +24668,15 @@
path = animation;
sourceTree = "<group>";
};
+ 716C4C3327EB608E00531467 /* system-preview */ = {
+ isa = PBXGroup;
+ children = (
+ 716C4C3527EB608E00531467 /* ARKitBadgeSystemImage.h */,
+ 716C4C3427EB608E00531467 /* ARKitBadgeSystemImage.mm */,
+ );
+ path = "system-preview";
+ sourceTree = "<group>";
+ };
716FA0D71DB26591007323CC /* controls */ = {
isa = PBXGroup;
children = (
@@ -26175,6 +26187,7 @@
AA2A5AB716A485A400975A25 /* speech */,
93085DB326E0068E000EC6A7 /* storage */,
41A023EA1A39DB7900F722CF /* streams */,
+ 716C4C3327EB608E00531467 /* system-preview */,
4644F7EA272A1C160055599E /* web-locks */,
FD315FA212B025B100C1A359 /* webaudio */,
57D8462A1FEAF57F00CA3682 /* webauthn */,
@@ -33598,6 +33611,7 @@
512DD8FD0D91E6AF000F89EE /* ArchiveFactory.h in Headers */,
512DD8FC0D91E6AF000F89EE /* ArchiveResource.h in Headers */,
512DD8F80D91E6AF000F89EE /* ArchiveResourceCollection.h in Headers */,
+ 716C4C3627EB60C900531467 /* ARKitBadgeSystemImage.h in Headers */,
FD5686CA13AC180200B69C68 /* AsyncAudioDecoder.h in Headers */,
E1CDE9221501916900862CC5 /* AsyncFileStream.h in Headers */,
0FFD4D6118651FA300512F6E /* AsyncScrollingCoordinator.h in Headers */,
Modified: trunk/Source/WebCore/platform/graphics/SystemImage.h (291816 => 291817)
--- trunk/Source/WebCore/platform/graphics/SystemImage.h 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/platform/graphics/SystemImage.h 2022-03-24 22:27:19 UTC (rev 291817)
@@ -37,6 +37,9 @@
ApplePayButton,
ApplePayLogo,
#endif
+#if USE(SYSTEM_PREVIEW)
+ ARKitBadge,
+#endif
};
class WEBCORE_EXPORT SystemImage : public RefCounted<SystemImage> {
@@ -69,6 +72,9 @@
, WebCore::SystemImageType::ApplePayButton,
WebCore::SystemImageType::ApplePayLogo
#endif
+#if USE(SYSTEM_PREVIEW)
+ , WebCore::SystemImageType::ARKitBadge
+#endif
>;
};
Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp (291816 => 291817)
--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp 2022-03-24 22:27:19 UTC (rev 291817)
@@ -39,6 +39,10 @@
#include <wtf/MathExtras.h>
#include <wtf/text/TextStream.h>
+#if USE(SYSTEM_PREVIEW)
+#include "ARKitBadgeSystemImage.h"
+#endif
+
namespace WebCore {
namespace DisplayList {
@@ -188,6 +192,12 @@
void Recorder::drawSystemImage(SystemImage& systemImage, const FloatRect& destinationRect)
{
+#if USE(SYSTEM_PREVIEW)
+ if (is<ARKitBadgeSystemImage>(systemImage)) {
+ if (auto image = downcast<ARKitBadgeSystemImage>(systemImage).image())
+ recordResourceUse(*image->nativeImage());
+ }
+#endif
recordDrawSystemImage(systemImage, destinationRect);
}
Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.h (291816 => 291817)
--- trunk/Source/WebCore/rendering/RenderThemeIOS.h 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.h 2022-03-24 22:27:19 UTC (rev 291817)
@@ -30,12 +30,6 @@
#include "CSSValueKey.h"
#include "RenderThemeCocoa.h"
-#if USE(SYSTEM_PREVIEW)
-#include "IOSurface.h"
-#include <wtf/RetainPtr.h>
-#endif
-
-OBJC_CLASS CIContext;
OBJC_CLASS UIImage;
namespace WebCore {
@@ -217,12 +211,6 @@
void adjustStyleForAlternateFormControlDesignTransition(RenderStyle&, const Element*) const;
-#if USE(SYSTEM_PREVIEW)
- RetainPtr<CIContext> m_ciContext;
- std::unique_ptr<IOSurface> m_largeBadgeSurface;
- std::unique_ptr<IOSurface> m_smallBadgeSurface;
-#endif
-
bool m_shouldMockBoldSystemFontForAccessibility { false };
};
Modified: trunk/Source/WebCore/rendering/RenderThemeIOS.mm (291816 => 291817)
--- trunk/Source/WebCore/rendering/RenderThemeIOS.mm 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebCore/rendering/RenderThemeIOS.mm 2022-03-24 22:27:19 UTC (rev 291817)
@@ -28,6 +28,7 @@
#if PLATFORM(IOS_FAMILY)
+#import "ARKitBadgeSystemImage.h"
#import "BitmapImage.h"
#import "CSSPrimitiveValue.h"
#import "CSSToLengthConversionData.h"
@@ -2007,186 +2008,9 @@
#endif
#if USE(SYSTEM_PREVIEW)
-static NSBundle *arKitBundle()
-{
- static NSBundle *arKitBundle = []() {
-#if PLATFORM(IOS_FAMILY_SIMULATOR)
- dlopen("/System/Library/PrivateFrameworks/AssetViewer.framework/AssetViewer", RTLD_NOW);
- return [NSBundle bundleForClass:NSClassFromString(@"ASVThumbnailView")];
-#else
- return [NSBundle bundleWithURL:[NSURL fileURLWithPath:@"/System/Library/PrivateFrameworks/AssetViewer.framework"]];
-#endif
- }();
-
- return arKitBundle;
-}
-
-static RetainPtr<CGPDFPageRef> loadARKitPDFPage(NSString *imageName)
-{
- NSURL *url = "" URLForResource:imageName withExtension:@"pdf"];
-
- if (!url)
- return nullptr;
-
- auto document = adoptCF(CGPDFDocumentCreateWithURL((CFURLRef)url));
- if (!document)
- return nullptr;
-
- if (!CGPDFDocumentGetNumberOfPages(document.get()))
- return nullptr;
-
- return CGPDFDocumentGetPage(document.get(), 1);
-}
-
-static CGPDFPageRef systemPreviewLogo()
-{
- static CGPDFPageRef logoPage = loadARKitPDFPage(@"ARKitBadge").leakRef();
- return logoPage;
-}
-
void RenderThemeIOS::paintSystemPreviewBadge(Image& image, const PaintInfo& paintInfo, const FloatRect& rect)
{
- static const int largeBadgeDimension = 70;
- static const int largeBadgeOffset = 20;
-
- static const int smallBadgeDimension = 35;
- static const int smallBadgeOffset = 8;
-
- static const int minimumSizeForLargeBadge = 240;
-
- bool useSmallBadge = rect.width() < minimumSizeForLargeBadge || rect.height() < minimumSizeForLargeBadge;
- int badgeOffset = useSmallBadge ? smallBadgeOffset : largeBadgeOffset;
- int badgeDimension = useSmallBadge ? smallBadgeDimension : largeBadgeDimension;
-
- int minimumDimension = badgeDimension + 2 * badgeOffset;
- if (rect.width() < minimumDimension || rect.height() < minimumDimension)
- return;
-
- CGRect absoluteBadgeRect = CGRectMake(rect.x() + rect.width() - badgeDimension - badgeOffset, rect.y() + badgeOffset, badgeDimension, badgeDimension);
- CGRect insetBadgeRect = CGRectMake(rect.width() - badgeDimension - badgeOffset, badgeOffset, badgeDimension, badgeDimension);
- CGRect badgeRect = CGRectMake(0, 0, badgeDimension, badgeDimension);
-
- CIImage *inputImage = [CIImage imageWithCGImage:image.nativeImage()->platformImage().get()];
-
- // Create a circle to be used for the clipping path in the badge, as well as the drop shadow.
- RetainPtr<CGPathRef> circle = adoptCF(CGPathCreateWithRoundedRect(absoluteBadgeRect, badgeDimension / 2, badgeDimension / 2, nullptr));
-
- auto& graphicsContext = paintInfo.context();
- if (graphicsContext.paintingDisabled())
- return;
-
- GraphicsContextStateSaver stateSaver(graphicsContext);
-
- CGContextRef ctx = graphicsContext.platformContext();
- if (!ctx)
- return;
-
- CGContextSaveGState(ctx);
-
- // Draw a drop shadow around the circle.
- // Use the GraphicsContext function, because it calculates the blur radius in context space,
- // rather than screen space.
- constexpr auto shadowColor = Color::black.colorWithAlphaByte(26);
- graphicsContext.setShadow(FloatSize { }, 16, shadowColor);
-
- // The circle must have an alpha channel value of 1 for the shadow color to appear.
- CGFloat circleColorComponents[4] = { 0, 0, 0, 1 };
- RetainPtr<CGColorRef> circleColor = adoptCF(CGColorCreate(sRGBColorSpaceRef(), circleColorComponents));
- CGContextSetFillColorWithColor(ctx, circleColor.get());
-
- // Clip out the circle to only show the shadow.
- CGContextBeginPath(ctx);
- CGContextAddRect(ctx, rect);
- CGContextAddPath(ctx, circle.get());
- CGContextClosePath(ctx);
- CGContextEOClip(ctx);
-
- // Draw a slightly smaller circle with a shadow, otherwise we'll see a fringe of the solid
- // black circle around the edges of the clipped path below.
- CGContextBeginPath(ctx);
- CGRect slightlySmallerAbsoluteBadgeRect = CGRectMake(absoluteBadgeRect.origin.x + 0.5, absoluteBadgeRect.origin.y + 0.5, badgeDimension - 1, badgeDimension - 1);
- RetainPtr<CGPathRef> slightlySmallerCircle = adoptCF(CGPathCreateWithRoundedRect(slightlySmallerAbsoluteBadgeRect, slightlySmallerAbsoluteBadgeRect.size.width / 2, slightlySmallerAbsoluteBadgeRect.size.height / 2, nullptr));
- CGContextAddPath(ctx, slightlySmallerCircle.get());
- CGContextClosePath(ctx);
- CGContextFillPath(ctx);
-
- CGContextRestoreGState(ctx);
-
- // Draw the blurred backdrop. Scale from intrinsic size to render size.
- CGAffineTransform transform = CGAffineTransformIdentity;
- transform = CGAffineTransformScale(transform, rect.width() / image.width(), rect.height() / image.height());
- CIImage *scaledImage = [inputImage imageByApplyingTransform:transform];
-
- // CoreImage coordinates are y-up, so we need to flip the badge rectangle within the image frame.
- CGRect flippedInsetBadgeRect = CGRectMake(insetBadgeRect.origin.x, rect.height() - insetBadgeRect.origin.y - insetBadgeRect.size.height, badgeDimension, badgeDimension);
-
- // Create a cropped region with pixel values extending outwards.
- CIImage *clampedImage = [scaledImage imageByClampingToRect:flippedInsetBadgeRect];
-
- // Blur.
- CIImage *blurredImage = [clampedImage imageByApplyingGaussianBlurWithSigma:10];
-
- // Saturate.
- CIFilter *saturationFilter = [CIFilter filterWithName:@"CIColorControls"];
- [saturationFilter setValue:blurredImage forKey:kCIInputImageKey];
- [saturationFilter setValue:@1.8 forKey:kCIInputSaturationKey];
-
- // Tint.
- CIFilter *tintFilter1 = [CIFilter filterWithName:@"CIConstantColorGenerator"];
- CIColor *tintColor1 = [CIColor colorWithRed:1 green:1 blue:1 alpha:0.18];
- [tintFilter1 setValue:tintColor1 forKey:kCIInputColorKey];
-
- // Blend the tint with the saturated output.
- CIFilter *sourceOverFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];
- [sourceOverFilter setValue:tintFilter1.outputImage forKey:kCIInputImageKey];
- [sourceOverFilter setValue:saturationFilter.outputImage forKey:kCIInputBackgroundImageKey];
-
- if (!m_ciContext)
- m_ciContext = [CIContext context];
-
- RetainPtr<CGImageRef> cgImage;
-#if HAVE(IOSURFACE_COREIMAGE_SUPPORT)
- // Crop the result to the badge location.
- CIImage *croppedImage = [sourceOverFilter.outputImage imageByCroppingToRect:flippedInsetBadgeRect];
- CIImage *translatedImage = [croppedImage imageByApplyingTransform:CGAffineTransformMakeTranslation(-flippedInsetBadgeRect.origin.x, -flippedInsetBadgeRect.origin.y)];
- IOSurfaceRef surface;
- if (useSmallBadge) {
- if (!m_smallBadgeSurface)
- m_smallBadgeSurface = IOSurface::create({ smallBadgeDimension, smallBadgeDimension }, DestinationColorSpace::SRGB());
- surface = m_smallBadgeSurface->surface();
- } else {
- if (!m_largeBadgeSurface)
- m_largeBadgeSurface = IOSurface::create({ largeBadgeDimension, largeBadgeDimension }, DestinationColorSpace::SRGB());
- surface = m_largeBadgeSurface->surface();
- }
- [m_ciContext render:translatedImage toIOSurface:surface bounds:badgeRect colorSpace:sRGBColorSpaceRef()];
- cgImage = useSmallBadge ? m_smallBadgeSurface->createImage() : m_largeBadgeSurface->createImage();
-#else
- cgImage = adoptCF([m_ciContext createCGImage:sourceOverFilter.outputImage fromRect:flippedInsetBadgeRect]);
-#endif
-
- // Before we render the result, we should clip to a circle around the badge rectangle.
- CGContextSaveGState(ctx);
- CGContextBeginPath(ctx);
- CGContextAddPath(ctx, circle.get());
- CGContextClosePath(ctx);
- CGContextClip(ctx);
-
- CGContextTranslateCTM(ctx, absoluteBadgeRect.origin.x, absoluteBadgeRect.origin.y);
- CGContextTranslateCTM(ctx, 0, badgeDimension);
- CGContextScaleCTM(ctx, 1, -1);
- CGContextDrawImage(ctx, badgeRect, cgImage.get());
-
- if (auto logo = systemPreviewLogo()) {
- CGSize pdfSize = CGPDFPageGetBoxRect(logo, kCGPDFMediaBox).size;
- CGFloat scaleX = badgeDimension / pdfSize.width;
- CGFloat scaleY = badgeDimension / pdfSize.height;
- CGContextScaleCTM(ctx, scaleX, scaleY);
- CGContextDrawPDFPage(ctx, logo);
- }
-
- CGContextFlush(ctx);
- CGContextRestoreGState(ctx);
+ paintInfo.context().drawSystemImage(ARKitBadgeSystemImage::create(image), rect);
}
#endif
Modified: trunk/Source/WebKit/ChangeLog (291816 => 291817)
--- trunk/Source/WebKit/ChangeLog 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebKit/ChangeLog 2022-03-24 22:27:19 UTC (rev 291817)
@@ -1,3 +1,19 @@
+2022-03-24 Antoine Quint <grao...@webkit.org>
+
+ DOM GPUP: paintSystemPreviewBadge (AR QuickLook element badge)
+ https://bugs.webkit.org/show_bug.cgi?id=238295
+ rdar://83580608
+
+ Reviewed by Dean Jackson.
+
+ Make sure we restore the Image on the ARKitBadgeSystemImage before we attempt to draw it.
+
+ * GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
+ (WebKit::RemoteDisplayListRecorder::drawSystemImage):
+ * Shared/WebCoreArgumentCoders.cpp:
+ (IPC::ArgumentCoder<Ref<SystemImage>>::encode):
+ (IPC::ArgumentCoder<Ref<SystemImage>>::decode):
+
2022-03-24 Michael Saboff <msab...@apple.com>
Update Sandbox profiles for system content path
Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp (291816 => 291817)
--- trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp 2022-03-24 22:27:19 UTC (rev 291817)
@@ -32,6 +32,10 @@
#include <WebCore/BitmapImage.h>
#include <WebCore/FilterResults.h>
+#if USE(SYSTEM_PREVIEW)
+#include <WebCore/ARKitBadgeSystemImage.h>
+#endif
+
namespace WebKit {
using namespace WebCore;
@@ -285,6 +289,17 @@
void RemoteDisplayListRecorder::drawSystemImage(SystemImage& systemImage, const FloatRect& destinationRect)
{
+#if USE(SYSTEM_PREVIEW)
+ if (is<ARKitBadgeSystemImage>(systemImage)) {
+ ARKitBadgeSystemImage& badge = downcast<ARKitBadgeSystemImage>(systemImage);
+ RefPtr nativeImage = resourceCache().cachedNativeImage({ badge.imageIdentifier(), m_webProcessIdentifier });
+ if (!nativeImage) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ badge.setImage(BitmapImage::create(WTFMove(nativeImage)));
+ }
+#endif
handleItem(DisplayList::DrawSystemImage(systemImage, destinationRect));
}
Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (291816 => 291817)
--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp 2022-03-24 22:22:33 UTC (rev 291816)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp 2022-03-24 22:27:19 UTC (rev 291817)
@@ -31,6 +31,7 @@
#include "StreamConnectionEncoder.h"
#include <_javascript_Core/GenericTypedArrayViewInlines.h>
#include <_javascript_Core/JSGenericTypedArrayViewInlines.h>
+#include <WebCore/ARKitBadgeSystemImage.h>
#include <WebCore/ApplePayButtonSystemImage.h>
#include <WebCore/ApplePayLogoSystemImage.h>
#include <WebCore/AuthenticationChallenge.h>
@@ -3173,6 +3174,11 @@
downcast<ApplePayLogoSystemImage>(systemImage.get()).encode(encoder);
return;
#endif
+#if USE(SYSTEM_PREVIEW)
+ case SystemImageType::ARKitBadge:
+ downcast<ARKitBadgeSystemImage>(systemImage.get()).encode(encoder);
+ return;
+#endif
}
ASSERT_NOT_REACHED();
@@ -3198,6 +3204,10 @@
case SystemImageType::ApplePayLogo:
return ApplePayLogoSystemImage::decode(decoder);
#endif
+#if USE(SYSTEM_PREVIEW)
+ case SystemImageType::ARKitBadge:
+ return ARKitBadgeSystemImage::decode(decoder);
+#endif
}
ASSERT_NOT_REACHED();