Title: [236854] trunk
Revision
236854
Author
wenson_hs...@apple.com
Date
2018-10-04 15:08:51 -0700 (Thu, 04 Oct 2018)

Log Message

[macOS] Fix some font attribute conversion bugs in preparation for "Font > Styles…" support in WebKit2
https://bugs.webkit.org/show_bug.cgi?id=190289
<rdar://problem/45020806>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Makes some small adjustments to fix two bugs in font attribute conversion logic. See below for more detail.

Tests:  FontManagerTests.AddFontShadowUsingFontOptions
        FontManagerTests.AddAndRemoveColorsUsingFontOptions

* editing/FontAttributeChanges.cpp:
(WebCore::cssValueListForShadow):
* editing/cocoa/FontAttributesCocoa.mm:

Currently, we bail from adding a font shadow if the shadow's offset is empty. However, valid shadow offsets may
have negative dimensions, so a check for `isZero()` should be used instead.

(WebCore::FontAttributes::createDictionary const):
* platform/mac/WebCoreNSFontManagerExtras.mm:

Fall back to a transparent background color; this allows senders to remove the current background color by just
removing NSBackgroundColorAttributeName from the attribute dictionary, rather than explicitly setting it to the
transparent color (this scenario is exercised when using "Font > Styles…" to specify a font style without a
background color).

(WebCore::computedFontAttributeChanges):

Tools:

Add new API tests to exercise two corner cases when using NSFontOptions ("Font > Styles…") to change font
attributes at the current selection.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h:
* TestWebKitAPI/Tests/mac/FontManagerTests.mm:
(webViewForFontManagerTesting):
(TestWebKitAPI::TEST):
* TestWebKitAPI/mac/TestFontOptions.h: Copied from Source/WebCore/editing/cocoa/FontAttributesCocoa.mm.
* TestWebKitAPI/mac/TestFontOptions.mm: Added.

Introduce TestFontOptions, which wraps the shared NSFontOptions and swizzles `-sharedFontOptions` to return a
global instance of itself. TestFontOptions supports several testing helpers to add or remove font shadows,
foreground colors, and background colors.

(sharedFontOptionsForTesting):
(+[TestFontOptions sharedInstance]):
(-[TestFontOptions initWithFontOptions:]):
(-[TestFontOptions selectedAttributes]):
(-[TestFontOptions fontOptions]):
(-[TestFontOptions shadowWidth]):
(-[TestFontOptions setShadowWidth:]):
(-[TestFontOptions shadowHeight]):
(-[TestFontOptions setShadowHeight:]):
(-[TestFontOptions setShadowBlurRadius:]):
(-[TestFontOptions setHasShadow:]):
(-[TestFontOptions foregroundColor]):
(-[TestFontOptions setForegroundColor:]):
(-[TestFontOptions backgroundColor]):
(-[TestFontOptions setBackgroundColor:]):
(-[TestFontOptions _dispatchFontAttributeChanges]):
(-[TestFontOptions convertAttributes:]):
(-[TestFontOptions setSelectedAttributes:isMultiple:]):
(-[TestFontOptions forwardInvocation:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (236853 => 236854)


--- trunk/Source/WebCore/ChangeLog	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Source/WebCore/ChangeLog	2018-10-04 22:08:51 UTC (rev 236854)
@@ -1,3 +1,33 @@
+2018-10-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [macOS] Fix some font attribute conversion bugs in preparation for "Font > Styles…" support in WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=190289
+        <rdar://problem/45020806>
+
+        Reviewed by Ryosuke Niwa.
+
+        Makes some small adjustments to fix two bugs in font attribute conversion logic. See below for more detail.
+
+        Tests:  FontManagerTests.AddFontShadowUsingFontOptions
+                FontManagerTests.AddAndRemoveColorsUsingFontOptions
+
+        * editing/FontAttributeChanges.cpp:
+        (WebCore::cssValueListForShadow):
+        * editing/cocoa/FontAttributesCocoa.mm:
+
+        Currently, we bail from adding a font shadow if the shadow's offset is empty. However, valid shadow offsets may
+        have negative dimensions, so a check for `isZero()` should be used instead.
+
+        (WebCore::FontAttributes::createDictionary const):
+        * platform/mac/WebCoreNSFontManagerExtras.mm:
+
+        Fall back to a transparent background color; this allows senders to remove the current background color by just
+        removing NSBackgroundColorAttributeName from the attribute dictionary, rather than explicitly setting it to the
+        transparent color (this scenario is exercised when using "Font > Styles…" to specify a font style without a
+        background color).
+
+        (WebCore::computedFontAttributeChanges):
+
 2018-10-03  Ryosuke Niwa  <rn...@webkit.org>
 
         MutationRecord doesn't keep JS wrappers of target, addedNodes, and removedNodes alive

Modified: trunk/Source/WebCore/editing/FontAttributeChanges.cpp (236853 => 236854)


--- trunk/Source/WebCore/editing/FontAttributeChanges.cpp	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Source/WebCore/editing/FontAttributeChanges.cpp	2018-10-04 22:08:51 UTC (rev 236854)
@@ -81,7 +81,7 @@
 
 static RefPtr<CSSValueList> cssValueListForShadow(const FontShadow& shadow)
 {
-    if (shadow.offset.isEmpty() && !shadow.blurRadius)
+    if (shadow.offset.isZero() && !shadow.blurRadius)
         return nullptr;
 
     auto list = CSSValueList::createCommaSeparated();

Modified: trunk/Source/WebCore/editing/cocoa/FontAttributesCocoa.mm (236853 => 236854)


--- trunk/Source/WebCore/editing/cocoa/FontAttributesCocoa.mm	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Source/WebCore/editing/cocoa/FontAttributesCocoa.mm	2018-10-04 22:08:51 UTC (rev 236854)
@@ -42,10 +42,8 @@
     if (backgroundColor.isValid())
         attributes[NSBackgroundColorAttributeName] = platformColor(backgroundColor);
 
-    if (fontShadow.color.isValid() && (!fontShadow.offset.isEmpty() || fontShadow.blurRadius)) {
-        auto shadow = fontShadow.createShadow();
-        attributes[NSShadowAttributeName] = shadow.get();
-    }
+    if (fontShadow.color.isValid() && (!fontShadow.offset.isZero() || fontShadow.blurRadius))
+        attributes[NSShadowAttributeName] = fontShadow.createShadow().get();
 
     if (subscriptOrSuperscript == SubscriptOrSuperscript::Subscript)
         attributes[NSSuperscriptAttributeName] = @(-1);

Modified: trunk/Source/WebCore/platform/mac/WebCoreNSFontManagerExtras.mm (236853 => 236854)


--- trunk/Source/WebCore/platform/mac/WebCoreNSFontManagerExtras.mm	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Source/WebCore/platform/mac/WebCoreNSFontManagerExtras.mm	2018-10-04 22:08:51 UTC (rev 236854)
@@ -126,7 +126,7 @@
 
     NSColor *convertedBackgroundColorA = [convertedAttributesA objectForKey:NSBackgroundColorAttributeName];
     if (convertedBackgroundColorA == [convertedAttributesB objectForKey:NSBackgroundColorAttributeName])
-        changes.setBackgroundColor(colorFromNSColor(convertedBackgroundColorA));
+        changes.setBackgroundColor(colorFromNSColor(convertedBackgroundColorA ?: NSColor.clearColor));
 
     changes.setFontChanges(computedFontChanges(fontManager, originalFontA, [convertedAttributesA objectForKey:NSFontAttributeName], [convertedAttributesB objectForKey:NSFontAttributeName]));
 

Modified: trunk/Tools/ChangeLog (236853 => 236854)


--- trunk/Tools/ChangeLog	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Tools/ChangeLog	2018-10-04 22:08:51 UTC (rev 236854)
@@ -1,3 +1,46 @@
+2018-10-04  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [macOS] Fix some font attribute conversion bugs in preparation for "Font > Styles…" support in WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=190289
+        <rdar://problem/45020806>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add new API tests to exercise two corner cases when using NSFontOptions ("Font > Styles…") to change font
+        attributes at the current selection.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h:
+        * TestWebKitAPI/Tests/mac/FontManagerTests.mm:
+        (webViewForFontManagerTesting):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/mac/TestFontOptions.h: Copied from Source/WebCore/editing/cocoa/FontAttributesCocoa.mm.
+        * TestWebKitAPI/mac/TestFontOptions.mm: Added.
+
+        Introduce TestFontOptions, which wraps the shared NSFontOptions and swizzles `-sharedFontOptions` to return a
+        global instance of itself. TestFontOptions supports several testing helpers to add or remove font shadows,
+        foreground colors, and background colors.
+
+        (sharedFontOptionsForTesting):
+        (+[TestFontOptions sharedInstance]):
+        (-[TestFontOptions initWithFontOptions:]):
+        (-[TestFontOptions selectedAttributes]):
+        (-[TestFontOptions fontOptions]):
+        (-[TestFontOptions shadowWidth]):
+        (-[TestFontOptions setShadowWidth:]):
+        (-[TestFontOptions shadowHeight]):
+        (-[TestFontOptions setShadowHeight:]):
+        (-[TestFontOptions setShadowBlurRadius:]):
+        (-[TestFontOptions setHasShadow:]):
+        (-[TestFontOptions foregroundColor]):
+        (-[TestFontOptions setForegroundColor:]):
+        (-[TestFontOptions backgroundColor]):
+        (-[TestFontOptions setBackgroundColor:]):
+        (-[TestFontOptions _dispatchFontAttributeChanges]):
+        (-[TestFontOptions convertAttributes:]):
+        (-[TestFontOptions setSelectedAttributes:isMultiple:]):
+        (-[TestFontOptions forwardInvocation:]):
+
 2018-10-04  Jiewen Tan  <jiewen_...@apple.com>
 
         [WebAuthN] Move time out control from WebProcess to UIProcess

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (236853 => 236854)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-10-04 22:08:51 UTC (rev 236854)
@@ -856,6 +856,7 @@
 		F4F137921D9B683E002BEC57 /* large-video-test-now-playing.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */; };
 		F4F405BC1D4C0D1C007A9707 /* full-size-autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */; };
 		F4F405BD1D4C0D1C007A9707 /* skinny-autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F405BB1D4C0CF8007A9707 /* skinny-autoplaying-video-with-audio.html */; };
+		F4F5BB5221667BAA002D06B9 /* TestFontOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4F5BB5121667BAA002D06B9 /* TestFontOptions.mm */; };
 		F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */; };
 		F4FA91831E61857B007B8C1D /* double-click-does-not-select-trailing-space.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */; };
 		F4FC077720F013B600CA043C /* significant-text-milestone.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4FC077620F0108100CA043C /* significant-text-milestone.html */; };
@@ -2114,6 +2115,8 @@
 		F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-test-now-playing.html"; sourceTree = "<group>"; };
 		F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "full-size-autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
 		F4F405BB1D4C0CF8007A9707 /* skinny-autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "skinny-autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
+		F4F5BB5021667BAA002D06B9 /* TestFontOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestFontOptions.h; sourceTree = "<group>"; };
+		F4F5BB5121667BAA002D06B9 /* TestFontOptions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestFontOptions.mm; sourceTree = "<group>"; };
 		F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewMacEditingTests.mm; sourceTree = "<group>"; };
 		F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "double-click-does-not-select-trailing-space.html"; path = "Tests/WebKitCocoa/double-click-does-not-select-trailing-space.html"; sourceTree = SOURCE_ROOT; };
 		F4FC077620F0108100CA043C /* significant-text-milestone.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "significant-text-milestone.html"; sourceTree = "<group>"; };
@@ -3174,6 +3177,8 @@
 				F46128CA211D475100D9FADB /* TestDraggingInfo.mm */,
 				F4E0A2B62122847400AF7C7F /* TestFilePromiseReceiver.h */,
 				F4E0A2B72122847400AF7C7F /* TestFilePromiseReceiver.mm */,
+				F4F5BB5021667BAA002D06B9 /* TestFontOptions.h */,
+				F4F5BB5121667BAA002D06B9 /* TestFontOptions.mm */,
 				F45D388F215A7B4B002A2979 /* TestInspectorBar.h */,
 				F45D3890215A7B4B002A2979 /* TestInspectorBar.mm */,
 				C08587BE13FE956C001EF4E5 /* WebKitAgnosticTest.h */,
@@ -3995,6 +4000,7 @@
 				7CCE7EA91A411A1D00447C4C /* TestBrowsingContextLoadDelegate.mm in Sources */,
 				F46128CB211D475100D9FADB /* TestDraggingInfo.mm in Sources */,
 				F4E0A2B82122847400AF7C7F /* TestFilePromiseReceiver.mm in Sources */,
+				F4F5BB5221667BAA002D06B9 /* TestFontOptions.mm in Sources */,
 				F45E15762112CE6200307E82 /* TestInputDelegate.mm in Sources */,
 				F45D3891215A7B4B002A2979 /* TestInspectorBar.mm in Sources */,
 				2D1C04A71D76298B000A6816 /* TestNavigationDelegate.mm in Sources */,

Modified: trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h (236853 => 236854)


--- trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Tools/TestWebKitAPI/Tests/TestWebKitAPI/mac/AppKitSPI.h	2018-10-04 22:08:51 UTC (rev 236854)
@@ -103,4 +103,8 @@
 - (void)menuNeedsUpdate:(NSMenu *)menu;
 @end
 
+@interface NSFontOptions : NSObject
++ (instancetype)sharedFontOptions;
+@end
+
 #endif // PLATFORM(MAC)

Modified: trunk/Tools/TestWebKitAPI/Tests/mac/FontManagerTests.mm (236853 => 236854)


--- trunk/Tools/TestWebKitAPI/Tests/mac/FontManagerTests.mm	2018-10-04 21:54:14 UTC (rev 236853)
+++ trunk/Tools/TestWebKitAPI/Tests/mac/FontManagerTests.mm	2018-10-04 22:08:51 UTC (rev 236854)
@@ -31,6 +31,7 @@
 #import "AppKitSPI.h"
 #import "NSFontPanelTesting.h"
 #import "PlatformUtilities.h"
+#import "TestFontOptions.h"
 #import "TestInspectorBar.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKWebViewPrivate.h>
@@ -113,12 +114,10 @@
 
 @end
 
-static RetainPtr<FontManagerTestWKWebView> webViewForFontManagerTesting(NSFontManager *fontManager)
+static RetainPtr<FontManagerTestWKWebView> webViewForFontManagerTesting(NSFontManager *fontManager, NSString *markup)
 {
     auto webView = adoptNS([[FontManagerTestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
-    [webView synchronouslyLoadHTMLString:@"<body contenteditable>"
-        "<span id='foo'>foo</span> <span id='bar'>bar</span> <span id='baz'>baz</span>"
-        "</body><script>document.body.addEventListener('input', event => lastInputEvent = event)</script>"];
+    [webView synchronouslyLoadHTMLString:markup];
     [webView stringByEvaluatingJavaScript:@"document.body.focus()"];
     [webView _setEditable:YES];
     fontManager.target = webView.get();
@@ -125,6 +124,13 @@
     return webView;
 }
 
+static RetainPtr<FontManagerTestWKWebView> webViewForFontManagerTesting(NSFontManager *fontManager)
+{
+    return webViewForFontManagerTesting(fontManager, @"<body contenteditable>"
+        "<span id='foo'>foo</span> <span id='bar'>bar</span> <span id='baz'>baz</span>"
+        "</body><script>document.body.addEventListener('input', event => lastInputEvent = event)</script>");
+}
+
 static RetainPtr<NSMenuItemCell> menuItemCellForFontAction(NSUInteger tag)
 {
     auto menuItem = adoptNS([[NSMenuItem alloc] init]);
@@ -474,6 +480,48 @@
     EXPECT_EQ(0, [[webView typingAttributes][NSSuperscriptAttributeName] integerValue]);
 }
 
+TEST(FontManagerTests, AddFontShadowUsingFontOptions)
+{
+    TestFontOptions *options = TestFontOptions.sharedInstance;
+    auto webView = webViewForFontManagerTesting(NSFontManager.sharedFontManager);
+
+    [webView selectWord:nil];
+    options.shadowWidth = 3;
+    options.shadowHeight = -3;
+    options.hasShadow = YES;
+
+    EXPECT_WK_STREQ("rgba(0, 0, 0, 0.333333) 3px -3px 0px", [webView stylePropertyAtSelectionStart:@"text-shadow"]);
+    [webView waitForNextPresentationUpdate];
+    NSShadow *shadow = [webView typingAttributes][NSShadowAttributeName];
+    EXPECT_EQ(shadow.shadowOffset.width, 3);
+    EXPECT_EQ(shadow.shadowOffset.height, -3);
+}
+
+TEST(FontManagerTests, AddAndRemoveColorsUsingFontOptions)
+{
+    TestFontOptions *options = TestFontOptions.sharedInstance;
+    auto webView = webViewForFontManagerTesting(NSFontManager.sharedFontManager, @"<body contenteditable>hello</body>");
+    [webView selectWord:nil];
+
+    options.backgroundColor = [NSColor colorWithRed:1 green:0 blue:0 alpha:0.2];
+    options.foregroundColor = [NSColor colorWithRed:0 green:0 blue:1 alpha:1];
+
+    EXPECT_WK_STREQ("rgb(0, 0, 255)", [webView stylePropertyAtSelectionStart:@"color"]);
+    EXPECT_WK_STREQ("rgba(255, 0, 0, 0.2)", [webView stylePropertyAtSelectionStart:@"background-color"]);
+    NSDictionary *attributes = [webView typingAttributes];
+    EXPECT_TRUE([[NSColor colorWithRed:0 green:0 blue:1 alpha:1] isEqual:attributes[NSForegroundColorAttributeName]]);
+    EXPECT_TRUE([[NSColor colorWithRed:1 green:0 blue:0 alpha:0.2] isEqual:attributes[NSBackgroundColorAttributeName]]);
+
+    options.backgroundColor = nil;
+    options.foregroundColor = nil;
+
+    EXPECT_WK_STREQ("rgb(0, 0, 0)", [webView stylePropertyAtSelectionStart:@"color"]);
+    EXPECT_WK_STREQ("rgba(0, 0, 0, 0)", [webView stylePropertyAtSelectionStart:@"background-color"]);
+    attributes = [webView typingAttributes];
+    EXPECT_NULL(attributes[NSForegroundColorAttributeName]);
+    EXPECT_NULL(attributes[NSBackgroundColorAttributeName]);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // PLATFORM(MAC) && WK_API_ENABLED

Copied: trunk/Tools/TestWebKitAPI/mac/TestFontOptions.h (from rev 236853, trunk/Source/WebCore/editing/cocoa/FontAttributesCocoa.mm) (0 => 236854)


--- trunk/Tools/TestWebKitAPI/mac/TestFontOptions.h	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/mac/TestFontOptions.h	2018-10-04 22:08:51 UTC (rev 236854)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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 PLATFORM(MAC) && WK_API_ENABLED
+
+#import <AppKit/AppKit.h>
+
+@interface TestFontOptions : NSObject
+
+@property (class, readonly) TestFontOptions *sharedInstance;
+@property (nonatomic, readonly) NSDictionary *selectedAttributes;
+@property (nonatomic, readonly) BOOL hasMultipleFonts;
+
+// Font shadow manipulation.
+@property (nonatomic) BOOL hasShadow;
+@property (nonatomic) CGFloat shadowWidth;
+@property (nonatomic) CGFloat shadowHeight;
+@property (nonatomic) CGFloat shadowBlurRadius;
+
+// Font colors.
+@property (nonatomic, copy) NSColor *foregroundColor;
+@property (nonatomic, copy) NSColor *backgroundColor;
+
+@end
+
+#endif

Added: trunk/Tools/TestWebKitAPI/mac/TestFontOptions.mm (0 => 236854)


--- trunk/Tools/TestWebKitAPI/mac/TestFontOptions.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/mac/TestFontOptions.mm	2018-10-04 22:08:51 UTC (rev 236854)
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2018 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 "TestFontOptions.h"
+
+#if PLATFORM(MAC) && WK_API_ENABLED
+
+#import "AppKitSPI.h"
+#import "ClassMethodSwizzler.h"
+#import <objc/runtime.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/SetForScope.h>
+
+using namespace TestWebKitAPI;
+
+static TestFontOptions *sharedFontOptionsForTesting()
+{
+    return TestFontOptions.sharedInstance;
+}
+
+@interface TestFontOptions ()
+- (instancetype)initWithFontOptions:(NSFontOptions *)fontOptions;
+@end
+
+@implementation TestFontOptions {
+    RetainPtr<NSFontOptions> _fontOptions;
+    CGSize _shadowOffset;
+    CGFloat _shadowBlurRadius;
+    BOOL _hasShadow;
+    BOOL _hasPendingShadowChanges;
+
+    RetainPtr<NSColor> _foregroundColor;
+    RetainPtr<NSColor> _backgroundColor;
+    BOOL _hasPendingColorChanges;
+
+    std::unique_ptr<ClassMethodSwizzler> _replaceFontOptionsSwizzler;
+    RetainPtr<NSDictionary> _selectedAttributes;
+    BOOL _hasMultipleFonts;
+}
+
+@synthesize hasShadow=_hasShadow;
+@synthesize shadowBlurRadius=_shadowBlurRadius;
+@synthesize hasMultipleFonts=_hasMultipleFonts;
+
++ (instancetype)sharedInstance
+{
+    static TestFontOptions *sharedInstance;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        NSFontOptions *sharedFontOptions = [NSClassFromString(@"NSFontOptions") sharedFontOptions];
+        sharedInstance = [[TestFontOptions alloc] initWithFontOptions:sharedFontOptions];
+    });
+    return sharedInstance;
+}
+
+- (instancetype)initWithFontOptions:(NSFontOptions *)fontOptions
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _fontOptions = fontOptions;
+    ASSERT(_fontOptions);
+
+    _shadowOffset = CGSizeZero;
+    _shadowBlurRadius = 0;
+    _replaceFontOptionsSwizzler = std::make_unique<ClassMethodSwizzler>(NSClassFromString(@"NSFontOptions"), @selector(sharedFontOptions), reinterpret_cast<IMP>(sharedFontOptionsForTesting));
+    _hasPendingShadowChanges = NO;
+    _hasMultipleFonts = NO;
+
+    return self;
+}
+
+- (NSDictionary *)selectedAttributes
+{
+    return _selectedAttributes.get();
+}
+
+- (NSFontOptions *)fontOptions
+{
+    return _fontOptions.get();
+}
+
+- (CGFloat)shadowWidth
+{
+    return _shadowOffset.width;
+}
+
+- (void)setShadowWidth:(CGFloat)shadowWidth
+{
+    if (_shadowOffset.width == shadowWidth)
+        return;
+
+    SetForScope<BOOL> hasPendingFontShadowChanges(_hasPendingShadowChanges, YES);
+    _shadowOffset.width = shadowWidth;
+    [self _dispatchFontAttributeChanges];
+}
+
+- (CGFloat)shadowHeight
+{
+    return _shadowOffset.height;
+}
+
+- (void)setShadowHeight:(CGFloat)shadowHeight
+{
+    if (_shadowOffset.height == shadowHeight)
+        return;
+
+    SetForScope<BOOL> hasPendingFontShadowChanges(_hasPendingShadowChanges, YES);
+    _shadowOffset.height = shadowHeight;
+    [self _dispatchFontAttributeChanges];
+}
+
+- (void)setShadowBlurRadius:(CGFloat)shadowBlurRadius
+{
+    if (_shadowBlurRadius == shadowBlurRadius)
+        return;
+
+    SetForScope<BOOL> hasPendingFontShadowChanges(_hasPendingShadowChanges, YES);
+    _shadowBlurRadius = shadowBlurRadius;
+    [self _dispatchFontAttributeChanges];
+}
+
+- (void)setHasShadow:(BOOL)hasShadow
+{
+    if (_hasShadow == hasShadow)
+        return;
+
+    SetForScope<BOOL> hasPendingFontShadowChanges(_hasPendingShadowChanges, YES);
+    _hasShadow = hasShadow;
+    [self _dispatchFontAttributeChanges];
+}
+
+- (NSColor *)foregroundColor
+{
+    return _foregroundColor.get();
+}
+
+- (void)setForegroundColor:(NSColor *)color
+{
+    SetForScope<BOOL> hasPendingColorChanges(_hasPendingColorChanges, YES);
+    _foregroundColor = adoptNS([color copy]);
+    [self _dispatchFontAttributeChanges];
+}
+
+- (NSColor *)backgroundColor
+{
+    return _backgroundColor.get();
+}
+
+- (void)setBackgroundColor:(NSColor *)color
+{
+    SetForScope<BOOL> hasPendingColorChanges(_hasPendingColorChanges, YES);
+    _backgroundColor = adoptNS([color copy]);
+    [self _dispatchFontAttributeChanges];
+}
+
+- (void)_dispatchFontAttributeChanges
+{
+    [NSFontManager.sharedFontManager.target performSelector:@selector(changeAttributes:) withObject:self];
+}
+
+- (NSDictionary *)convertAttributes:(NSDictionary *)attributes
+{
+    auto convertedAttributes = adoptNS([attributes mutableCopy]);
+
+    if (_hasPendingShadowChanges) {
+        if (_hasShadow) {
+            auto shadow = adoptNS([[NSShadow alloc] init]);
+            [shadow setShadowBlurRadius:_shadowBlurRadius];
+            [shadow setShadowOffset:_shadowOffset];
+            [convertedAttributes setObject:shadow.get() forKey:NSShadowAttributeName];
+        } else
+            [convertedAttributes removeObjectForKey:NSShadowAttributeName];
+    }
+
+    if (_hasPendingColorChanges) {
+        if (_foregroundColor)
+            [convertedAttributes setObject:_foregroundColor.get() forKey:NSForegroundColorAttributeName];
+        else
+            [convertedAttributes removeObjectForKey:NSForegroundColorAttributeName];
+
+        if (_backgroundColor)
+            [convertedAttributes setObject:_backgroundColor.get() forKey:NSBackgroundColorAttributeName];
+        else
+            [convertedAttributes removeObjectForKey:NSBackgroundColorAttributeName];
+    }
+
+    return convertedAttributes.autorelease();
+}
+
+- (void)setSelectedAttributes:(NSDictionary *)attributes isMultiple:(BOOL)multiple
+{
+    _hasMultipleFonts = multiple;
+    _selectedAttributes = attributes;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+    if ([_fontOptions respondsToSelector:invocation.selector]) {
+        [invocation invokeWithTarget:_fontOptions.get()];
+        return;
+    }
+
+    [super forwardInvocation:invocation];
+}
+
+@end
+
+#endif // PLATFORM(MAC) && WK_API_ENABLED
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to