Diff
Modified: trunk/LayoutTests/ChangeLog (277273 => 277274)
--- trunk/LayoutTests/ChangeLog 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/LayoutTests/ChangeLog 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1,3 +1,24 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] ImageOverlayController should paint selection quads instead of bounding rects
+ https://bugs.webkit.org/show_bug.cgi?id=225585
+ <rdar://problem/77725745>
+
+ Reviewed by Tim Horton.
+
+ Add a new layout test to cover the change. Currently, the below test case renders a visible selection rect in
+ the image overlay since we render the bounding rect of the overlay text quad, which intersects with the image
+ overlay's bounds. However, the text quad is positioned outside of the image overlay, so there shouldn't be any
+ visible selection rect. As such, this test is expected to render the same content as a plain image (even without
+ an image overlay).
+
+ Unfortunately, I couldn't write a matching ref-test for the case where the selection rect is inside the bounds
+ of the image overlay, since doing so led to tiny subpixel differences between the transparent image case (using
+ `ImageOverlayController`) and the regular image overlay selection case.
+
+ * fast/images/image-extraction/mac/select-rotated-transparent-image-overlay-expected.html: Added.
+ * fast/images/image-extraction/mac/select-rotated-transparent-image-overlay.html: Added.
+
2021-05-10 Aditya Keerthi <[email protected]>
[iPadOS] Do not present custom input peripherals when switching back to a tab with a focused element
Added: trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay-expected.html (0 => 277274)
--- trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay-expected.html (rev 0)
+++ trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay-expected.html 2021-05-10 18:10:03 UTC (rev 277274)
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body, html {
+ margin: 0;
+}
+
+img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 400px;
+ height: 400px;
+}
+</style>
+</head>
+<body>
+<img src=""
+</body>
+</html>
\ No newline at end of file
Added: trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay.html (0 => 277274)
--- trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay.html (rev 0)
+++ trunk/LayoutTests/fast/images/image-extraction/mac/select-rotated-transparent-image-overlay.html 2021-05-10 18:10:03 UTC (rev 277274)
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.back {
+ background-size: contain;
+ background-image: url(../../resources/green-400x400.png);
+}
+
+.front {
+ opacity: 0;
+}
+
+body, html {
+ margin: 0;
+}
+
+.front, .back {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 400px;
+ height: 400px;
+}
+</style>
+</head>
+<body>
+<div class="back"></div>
+<img class="front" src=""
+<div class="bar"></div>
+<script>
+addEventListener("load", () => {
+ let image = document.querySelector("img");
+ internals.installImageOverlay(image, [
+ {
+ topLeft : new DOMPointReadOnly(0.5, 1.5),
+ topRight : new DOMPointReadOnly(1.5, 0.5),
+ bottomRight : new DOMPointReadOnly(2, 1),
+ bottomLeft : new DOMPointReadOnly(1, 2),
+ children: [
+ {
+ text : "hello",
+ topLeft : new DOMPointReadOnly(0.5, 1.5),
+ topRight : new DOMPointReadOnly(1.5, 0.5),
+ bottomRight : new DOMPointReadOnly(2, 1),
+ bottomLeft : new DOMPointReadOnly(1, 2),
+ }
+ ]
+ }
+ ]);
+
+ getSelection().selectAllChildren(internals.shadowRoot(image).querySelector(".image-overlay-text"));
+});
+</script>
+</body>
+</html>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (277273 => 277274)
--- trunk/Source/WebCore/ChangeLog 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/ChangeLog 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1,3 +1,83 @@
+2021-05-10 Wenson Hsieh <[email protected]>
+
+ [macOS] ImageOverlayController should paint selection quads instead of bounding rects
+ https://bugs.webkit.org/show_bug.cgi?id=225585
+ <rdar://problem/77725745>
+
+ Reviewed by Tim Horton.
+
+ Teach `SelectionRectGatherer` (now renamed to `SelectionGeometryGatherer`) to emit quads, rather than bounding
+ rects around each quad. We use these quads in `ImageOverlayController` to render selection quads via page
+ overlay (i.e., in the case where the image containing the overlay is transparent).
+
+ Test: fast/images/image-extraction/mac/select-rotated-transparent-image-overlay.html
+
+ * Headers.cmake:
+ * SourcesCocoa.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * editing/SelectionGeometryGatherer.cpp: Renamed from Source/WebCore/editing/SelectionRectGatherer.cpp.
+
+ Rename `SelectionRectGatherer` to `SelectionGeometryGatherer`, to reflect the fact that this helper class now
+ aggregates both selection quads and gap rects.
+
+ (WebCore::SelectionGeometryGatherer::SelectionGeometryGatherer):
+ (WebCore::SelectionGeometryGatherer::addQuad):
+
+ Rename `addRect` to `addQuad`, and make it take a `FloatQuad` instead.
+
+ (WebCore::SelectionGeometryGatherer::addGapRects):
+ (WebCore::SelectionGeometryGatherer::Notifier::Notifier):
+ (WebCore::SelectionGeometryGatherer::Notifier::~Notifier):
+ (WebCore::SelectionGeometryGatherer::boundingRects const):
+ (WebCore::SelectionGeometryGatherer::clearAndCreateNotifier):
+ * editing/SelectionGeometryGatherer.h: Renamed from Source/WebCore/editing/SelectionRectGatherer.h.
+ (WebCore::SelectionGeometryGatherer::setTextOnly):
+ (WebCore::SelectionGeometryGatherer::isTextOnly const):
+ * html/HTMLElement.cpp:
+ (WebCore::HTMLElement::updateWithImageExtractionResult):
+
+ Minor tweak - don't add any margin around the word when the line only contains a single word.
+
+ * page/ImageOverlayController.cpp:
+ (WebCore::ImageOverlayController::selectionQuadsDidChange):
+
+ Rename `selectionRectsDidChange` to `selectionQuadsDidChange`, and take a `FloatQuad` in absolute coordinates
+ instead of a `LayoutRect`. Store these quads in `m_overlaySelectionQuads` (also renamed from
+ `m_overlaySelectionRects`).
+
+ (WebCore::ImageOverlayController::uninstallPageOverlayIfNeeded):
+ (WebCore::ImageOverlayController::drawRect):
+
+ Make a few changes when painting selections using the `ImageOverlayController`:
+
+ 1. Instead of painting with `fillRect()`, coalesce all of the collected selection quads into a single `Path`
+ object, and pass that `Path` into `fillPath()`. This allows us to render each piece of selected content as a
+ quad instead of a bounding rect, and additionally prevents us from rendering overlapping selections
+ when using `ImageOverlayController`.
+
+ 2. Clip selections to the absolute bounds of the image overlay host element's renderer, which prevents the new
+ selection quads from spilling out of the host element.
+
+ (WebCore::ImageOverlayController::selectionRectsDidChange): Deleted.
+ * page/ImageOverlayController.h:
+ * rendering/RenderSelectionInfo.cpp:
+ (WebCore::RenderSelectionInfo::RenderSelectionInfo):
+ * rendering/RenderSelectionInfo.h:
+ (WebCore::RenderSelectionInfo::collectedSelectionQuads const):
+ (WebCore::RenderSelectionInfo::collectedSelectionRects const): Deleted.
+
+ More minor refactoring: rename `collectedSelectionRects` to `collectedSelectionQuads`, and make it take the
+ original `FloatQuad` instead of the quad's bounding box.
+
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::collectSelectionGeometriesForLineBoxes):
+ * rendering/RenderText.h:
+ * rendering/SelectionRangeData.cpp:
+ (WebCore::SelectionRangeData::SelectionRangeData):
+ (WebCore::SelectionRangeData::set):
+ (WebCore::SelectionRangeData::apply):
+ * rendering/SelectionRangeData.h:
+
2021-05-10 Eric Carlson <[email protected]>
[GPUP-MSE] Implement time changed callback
Modified: trunk/Source/WebCore/Headers.cmake (277273 => 277274)
--- trunk/Source/WebCore/Headers.cmake 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/Headers.cmake 2021-05-10 18:10:03 UTC (rev 277274)
@@ -575,7 +575,7 @@
editing/FrameSelection.h
editing/HTMLInterchange.h
editing/InlineRunAndOffset.h
- editing/SelectionRectGatherer.h
+ editing/SelectionGeometryGatherer.h
editing/SerializedAttachmentData.h
editing/SmartReplace.h
editing/SpellChecker.h
Modified: trunk/Source/WebCore/SourcesCocoa.txt (277273 => 277274)
--- trunk/Source/WebCore/SourcesCocoa.txt 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/SourcesCocoa.txt 2021-05-10 18:10:03 UTC (rev 277274)
@@ -141,7 +141,7 @@
dom/ios/MouseEventIOS.cpp
dom/ios/PointerEventIOS.cpp
dom/ios/TouchEvents.cpp
-editing/SelectionRectGatherer.cpp
+editing/SelectionGeometryGatherer.cpp
editing/SmartReplaceCF.cpp
editing/cocoa/AlternativeTextContextController.mm
editing/cocoa/AlternativeTextUIController.mm
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (277273 => 277274)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1477,7 +1477,7 @@
5130F2F624AEA60A00E1D0A0 /* GameControllerSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5130F2F424AEA60300E1D0A0 /* GameControllerSoftLink.mm */; };
51327D6011A33A2B004F9D65 /* SinkDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 51327D5E11A33A2B004F9D65 /* SinkDocument.h */; };
513F14540AB634C400094DDF /* IconLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 513F14520AB634C400094DDF /* IconLoader.h */; };
- 51405C89190B014400754F94 /* SelectionRectGatherer.h in Headers */ = {isa = PBXBuildFile; fileRef = 51405C87190B014400754F94 /* SelectionRectGatherer.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 51405C89190B014400754F94 /* SelectionGeometryGatherer.h in Headers */ = {isa = PBXBuildFile; fileRef = 51405C87190B014400754F94 /* SelectionGeometryGatherer.h */; settings = {ATTRIBUTES = (Private, ); }; };
514129991C6976900059E714 /* IDBRequestCompletionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 514129971C6976150059E714 /* IDBRequestCompletionEvent.h */; };
5143B2631DDD15200014FAC6 /* LinkIcon.h in Headers */ = {isa = PBXBuildFile; fileRef = 5143B2621DDD14900014FAC6 /* LinkIcon.h */; settings = {ATTRIBUTES = (Private, ); }; };
5145B10A1BC48E2E00E86219 /* IDBResourceIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 5145B1081BC4890B00E86219 /* IDBResourceIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -8715,8 +8715,8 @@
51327D5F11A33A2B004F9D65 /* SinkDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SinkDocument.cpp; sourceTree = "<group>"; };
513F14510AB634C400094DDF /* IconLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IconLoader.cpp; sourceTree = "<group>"; };
513F14520AB634C400094DDF /* IconLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IconLoader.h; sourceTree = "<group>"; };
- 51405C86190B014400754F94 /* SelectionRectGatherer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionRectGatherer.cpp; sourceTree = "<group>"; };
- 51405C87190B014400754F94 /* SelectionRectGatherer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionRectGatherer.h; sourceTree = "<group>"; };
+ 51405C86190B014400754F94 /* SelectionGeometryGatherer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionGeometryGatherer.cpp; sourceTree = "<group>"; };
+ 51405C87190B014400754F94 /* SelectionGeometryGatherer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionGeometryGatherer.h; sourceTree = "<group>"; };
514129961C6976150059E714 /* IDBRequestCompletionEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBRequestCompletionEvent.cpp; sourceTree = "<group>"; };
514129971C6976150059E714 /* IDBRequestCompletionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBRequestCompletionEvent.h; sourceTree = "<group>"; };
5141299A1C6C166D0059E714 /* JSIDBIndexCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBIndexCustom.cpp; sourceTree = "<group>"; };
@@ -23427,8 +23427,8 @@
2DF512CC1D873E47001D6780 /* ReplaceRangeWithTextCommand.h */,
93309DBA099E64910056E581 /* ReplaceSelectionCommand.cpp */,
93309DBB099E64910056E581 /* ReplaceSelectionCommand.h */,
- 51405C86190B014400754F94 /* SelectionRectGatherer.cpp */,
- 51405C87190B014400754F94 /* SelectionRectGatherer.h */,
+ 51405C86190B014400754F94 /* SelectionGeometryGatherer.cpp */,
+ 51405C87190B014400754F94 /* SelectionGeometryGatherer.h */,
F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */,
93309DC0099E64910056E581 /* SetNodeAttributeCommand.cpp */,
93309DC1099E64910056E581 /* SetNodeAttributeCommand.h */,
@@ -34974,8 +34974,8 @@
2D5BC42716F882EE007048D0 /* SecurityPolicyViolationEvent.h in Headers */,
B2C3DA2F0D006C1D00EF6F26 /* SegmentedString.h in Headers */,
BEA807C90F714A0300524199 /* SelectionGeometry.h in Headers */,
+ 51405C89190B014400754F94 /* SelectionGeometryGatherer.h in Headers */,
4465D7BD2536D05E0016666D /* SelectionRangeData.h in Headers */,
- 51405C89190B014400754F94 /* SelectionRectGatherer.h in Headers */,
98CBC8052618F68C001593C8 /* SelectionRestorationMode.h in Headers */,
E44B4BB4141650D7002B1D8B /* SelectorChecker.h in Headers */,
432D3FE818A8658400D7DC03 /* SelectorCheckerTestFunctions.h in Headers */,
Copied: trunk/Source/WebCore/editing/SelectionGeometryGatherer.cpp (from rev 277273, trunk/Source/WebCore/editing/SelectionRectGatherer.cpp) (0 => 277274)
--- trunk/Source/WebCore/editing/SelectionGeometryGatherer.cpp (rev 0)
+++ trunk/Source/WebCore/editing/SelectionGeometryGatherer.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "config.h"
+#include "SelectionGeometryGatherer.h"
+
+#if ENABLE(SERVICE_CONTROLS)
+
+#include "Editor.h"
+#include "EditorClient.h"
+#include "Frame.h"
+#include "ImageOverlayController.h"
+#include "RenderView.h"
+#include "ServicesOverlayController.h"
+
+namespace WebCore {
+
+SelectionGeometryGatherer::SelectionGeometryGatherer(RenderView& renderView)
+ : m_renderView(renderView)
+ , m_isTextOnly(true)
+{
+}
+
+void SelectionGeometryGatherer::addQuad(RenderLayerModelObject *repaintContainer, const FloatQuad& quad)
+{
+ if (!quad.boundingBoxIsEmpty())
+ m_quads.append(repaintContainer ? repaintContainer->localToAbsoluteQuad(quad) : quad);
+}
+
+void SelectionGeometryGatherer::addGapRects(RenderLayerModelObject *repaintContainer, const GapRects& rects)
+{
+ if (repaintContainer) {
+ GapRects absoluteGapRects;
+ absoluteGapRects.uniteLeft(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.left())).boundingBox()));
+ absoluteGapRects.uniteCenter(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.center())).boundingBox()));
+ absoluteGapRects.uniteRight(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.right())).boundingBox()));
+ m_gapRects.append(absoluteGapRects);
+ } else
+ m_gapRects.append(rects);
+}
+
+SelectionGeometryGatherer::Notifier::Notifier(SelectionGeometryGatherer& gatherer)
+ : m_gatherer(gatherer)
+{
+}
+
+SelectionGeometryGatherer::Notifier::~Notifier()
+{
+ auto page = m_gatherer.m_renderView.view().frame().page();
+ if (!page)
+ return;
+
+ page->servicesOverlayController().selectionRectsDidChange(m_gatherer.boundingRects(), m_gatherer.m_gapRects, m_gatherer.isTextOnly());
+ page->imageOverlayController().selectionQuadsDidChange(m_gatherer.m_renderView.frame(), m_gatherer.m_quads);
+}
+
+Vector<LayoutRect> SelectionGeometryGatherer::boundingRects() const
+{
+ return m_quads.map([](auto& quad) {
+ return LayoutRect { quad.boundingBox() };
+ });
+}
+
+std::unique_ptr<SelectionGeometryGatherer::Notifier> SelectionGeometryGatherer::clearAndCreateNotifier()
+{
+ m_quads.clear();
+ m_gapRects.clear();
+ m_isTextOnly = true;
+
+ return makeUnique<Notifier>(*this);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_CONTROLS)
Copied: trunk/Source/WebCore/editing/SelectionGeometryGatherer.h (from rev 277273, trunk/Source/WebCore/editing/SelectionRectGatherer.h) (0 => 277274)
--- trunk/Source/WebCore/editing/SelectionGeometryGatherer.h (rev 0)
+++ trunk/Source/WebCore/editing/SelectionGeometryGatherer.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2014 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 ENABLE(SERVICE_CONTROLS)
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatQuad;
+class LayoutRect;
+class RenderLayerModelObject;
+class RenderView;
+
+struct GapRects;
+
+class SelectionGeometryGatherer {
+ WTF_MAKE_NONCOPYABLE(SelectionGeometryGatherer);
+
+public:
+ SelectionGeometryGatherer(RenderView&);
+
+ void addQuad(RenderLayerModelObject *repaintContainer, const FloatQuad&);
+ void addGapRects(RenderLayerModelObject *repaintContainer, const GapRects&);
+ void setTextOnly(bool isTextOnly) { m_isTextOnly = isTextOnly; }
+ bool isTextOnly() const { return m_isTextOnly; }
+
+ class Notifier {
+ WTF_MAKE_FAST_ALLOCATED;
+ WTF_MAKE_NONCOPYABLE(Notifier);
+ public:
+ Notifier(SelectionGeometryGatherer&);
+ ~Notifier();
+
+ private:
+ SelectionGeometryGatherer& m_gatherer;
+ };
+
+ std::unique_ptr<Notifier> clearAndCreateNotifier();
+
+private:
+ Vector<LayoutRect> boundingRects() const;
+
+ RenderView& m_renderView;
+
+ // All rects are in RenderView coordinates.
+ Vector<FloatQuad> m_quads;
+ Vector<GapRects> m_gapRects;
+ bool m_isTextOnly;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SERVICE_CONTROLS)
Deleted: trunk/Source/WebCore/editing/SelectionRectGatherer.cpp (277273 => 277274)
--- trunk/Source/WebCore/editing/SelectionRectGatherer.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/editing/SelectionRectGatherer.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "config.h"
-#include "SelectionRectGatherer.h"
-
-#if ENABLE(SERVICE_CONTROLS)
-
-#include "Editor.h"
-#include "EditorClient.h"
-#include "Frame.h"
-#include "ImageOverlayController.h"
-#include "RenderView.h"
-#include "ServicesOverlayController.h"
-
-namespace WebCore {
-
-SelectionRectGatherer::SelectionRectGatherer(RenderView& renderView)
- : m_renderView(renderView)
- , m_isTextOnly(true)
-{
-}
-
-void SelectionRectGatherer::addRect(RenderLayerModelObject *repaintContainer, const LayoutRect& rect)
-{
- if (!rect.isEmpty()) {
- if (repaintContainer)
- m_rects.append(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rect)).boundingBox()));
- else
- m_rects.append(rect);
- }
-}
-
-void SelectionRectGatherer::addGapRects(RenderLayerModelObject *repaintContainer, const GapRects& rects)
-{
- if (repaintContainer) {
- GapRects absoluteGapRects;
- absoluteGapRects.uniteLeft(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.left())).boundingBox()));
- absoluteGapRects.uniteCenter(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.center())).boundingBox()));
- absoluteGapRects.uniteRight(LayoutRect(repaintContainer->localToAbsoluteQuad(FloatQuad(rects.right())).boundingBox()));
- m_gapRects.append(absoluteGapRects);
- } else
- m_gapRects.append(rects);
-}
-
-SelectionRectGatherer::Notifier::Notifier(SelectionRectGatherer& gatherer)
- : m_gatherer(gatherer)
-{
-}
-
-SelectionRectGatherer::Notifier::~Notifier()
-{
- auto page = m_gatherer.m_renderView.view().frame().page();
- if (!page)
- return;
-
- page->servicesOverlayController().selectionRectsDidChange(m_gatherer.m_rects, m_gatherer.m_gapRects, m_gatherer.isTextOnly());
- page->imageOverlayController().selectionRectsDidChange(m_gatherer.m_renderView.frame(), m_gatherer.m_rects);
-}
-
-std::unique_ptr<SelectionRectGatherer::Notifier> SelectionRectGatherer::clearAndCreateNotifier()
-{
- m_rects.clear();
- m_gapRects.clear();
- m_isTextOnly = true;
-
- return makeUnique<Notifier>(*this);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SERVICE_CONTROLS)
Deleted: trunk/Source/WebCore/editing/SelectionRectGatherer.h (277273 => 277274)
--- trunk/Source/WebCore/editing/SelectionRectGatherer.h 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/editing/SelectionRectGatherer.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2014 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 ENABLE(SERVICE_CONTROLS)
-
-#include <wtf/Noncopyable.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class LayoutRect;
-class RenderLayerModelObject;
-class RenderView;
-
-struct GapRects;
-
-class SelectionRectGatherer {
- WTF_MAKE_NONCOPYABLE(SelectionRectGatherer);
-
-public:
- SelectionRectGatherer(RenderView&);
-
- void addRect(RenderLayerModelObject *repaintContainer, const LayoutRect&);
- void addGapRects(RenderLayerModelObject *repaintContainer, const GapRects&);
- void setTextOnly(bool isTextOnly) { m_isTextOnly = isTextOnly; }
- bool isTextOnly() const { return m_isTextOnly; }
-
- class Notifier {
- WTF_MAKE_FAST_ALLOCATED;
- WTF_MAKE_NONCOPYABLE(Notifier);
- public:
- Notifier(SelectionRectGatherer&);
- ~Notifier();
-
- private:
- SelectionRectGatherer& m_gatherer;
- };
-
- std::unique_ptr<Notifier> clearAndCreateNotifier();
-
-private:
- RenderView& m_renderView;
-
- // All rects are in RenderView coordinates.
- Vector<LayoutRect> m_rects;
- Vector<GapRects> m_gapRects;
- bool m_isTextOnly;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(SERVICE_CONTROLS)
Modified: trunk/Source/WebCore/html/HTMLElement.cpp (277273 => 277274)
--- trunk/Source/WebCore/html/HTMLElement.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/html/HTMLElement.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1384,11 +1384,12 @@
if (child.normalizedQuad.isEmpty())
continue;
- constexpr float horizontalMarginToMinimizeSelectionGaps = 0.125;
- float horizontalOffset = -horizontalMarginToMinimizeSelectionGaps;
- float horizontalExtent = horizontalMarginToMinimizeSelectionGaps;
+ bool lineHasOneChild = line.children.size() == 1;
+ float horizontalMarginToMinimizeSelectionGaps = lineHasOneChild ? 0 : 0.125;
+ float horizontalOffset = lineHasOneChild ? 0 : -horizontalMarginToMinimizeSelectionGaps;
+ float horizontalExtent = lineHasOneChild ? 0 : horizontalMarginToMinimizeSelectionGaps;
- if (line.children.size() == 1) {
+ if (lineHasOneChild) {
horizontalOffset += offsetsAlongHorizontalAxis[childIndex].begin();
horizontalExtent += offsetsAlongHorizontalAxis[childIndex].end();
} else if (!childIndex) {
Modified: trunk/Source/WebCore/page/ImageOverlayController.cpp (277273 => 277274)
--- trunk/Source/WebCore/page/ImageOverlayController.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/page/ImageOverlayController.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -32,7 +32,6 @@
#include "Editor.h"
#include "Frame.h"
#include "FrameSelection.h"
-#include "GapRects.h"
#include "GraphicsContext.h"
#include "HTMLElement.h"
#include "IntRect.h"
@@ -46,12 +45,14 @@
namespace WebCore {
+class FloatQuad;
+
ImageOverlayController::ImageOverlayController(Page& page)
: m_page(makeWeakPtr(page))
{
}
-void ImageOverlayController::selectionRectsDidChange(Frame& frame, const Vector<LayoutRect>& rects)
+void ImageOverlayController::selectionQuadsDidChange(Frame& frame, const Vector<FloatQuad>& quads)
{
if (!m_page || !m_page->chrome().client().needsImageOverlayControllerForSelectionPainting())
return;
@@ -60,7 +61,7 @@
return;
auto overlayHostRenderer = ([&] () -> RenderElement* {
- if (rects.isEmpty())
+ if (quads.isEmpty())
return nullptr;
auto selectedRange = frame.selection().selection().range();
@@ -84,7 +85,8 @@
return;
}
- m_overlaySelectionRects = rects;
+ m_overlaySelectionQuads = quads;
+ m_selectionOverlayBounds = overlayHostRenderer->absoluteBoundingBoxRect();
m_selectionBackgroundColor = overlayHostRenderer->selectionBackgroundColor();
m_currentOverlayDocument = makeWeakPtr(overlayHostRenderer->document());
@@ -116,7 +118,8 @@
void ImageOverlayController::uninstallPageOverlayIfNeeded()
{
- m_overlaySelectionRects.clear();
+ m_selectionOverlayBounds = { };
+ m_overlaySelectionQuads.clear();
m_selectionBackgroundColor = Color::transparentBlack;
m_currentOverlayDocument = nullptr;
@@ -142,9 +145,23 @@
GraphicsContextStateSaver stateSaver(context);
context.clearRect(dirtyRect);
+
+ if (m_overlaySelectionQuads.isEmpty())
+ return;
+
+ Path coalescedSelectionPath;
+ for (auto& quad : m_overlaySelectionQuads) {
+ coalescedSelectionPath.moveTo(quad.p1());
+ coalescedSelectionPath.addLineTo(quad.p2());
+ coalescedSelectionPath.addLineTo(quad.p3());
+ coalescedSelectionPath.addLineTo(quad.p4());
+ coalescedSelectionPath.addLineTo(quad.p1());
+ coalescedSelectionPath.closeSubpath();
+ }
+
context.setFillColor(m_selectionBackgroundColor);
- for (auto& rect : m_overlaySelectionRects)
- context.fillRect(rect);
+ context.clip(m_selectionOverlayBounds);
+ context.fillPath(coalescedSelectionPath);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/page/ImageOverlayController.h (277273 => 277274)
--- trunk/Source/WebCore/page/ImageOverlayController.h 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/page/ImageOverlayController.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -36,7 +36,7 @@
class Frame;
class GraphicsContext;
class IntRect;
-class LayoutRect;
+class FloatQuad;
class Page;
class RenderElement;
struct GapRects;
@@ -46,7 +46,7 @@
public:
explicit ImageOverlayController(Page&);
- void selectionRectsDidChange(Frame&, const Vector<LayoutRect>&);
+ void selectionQuadsDidChange(Frame&, const Vector<FloatQuad>&);
void documentDetached(const Document&);
private:
@@ -63,7 +63,8 @@
WeakPtr<Page> m_page;
RefPtr<PageOverlay> m_overlay;
WeakPtr<Document> m_currentOverlayDocument;
- Vector<LayoutRect> m_overlaySelectionRects;
+ Vector<FloatQuad> m_overlaySelectionQuads;
+ LayoutRect m_selectionOverlayBounds;
Color m_selectionBackgroundColor { Color::transparentBlack };
};
Modified: trunk/Source/WebCore/rendering/RenderSelectionInfo.cpp (277273 => 277274)
--- trunk/Source/WebCore/rendering/RenderSelectionInfo.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/RenderSelectionInfo.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -47,7 +47,7 @@
{
if (renderer.canUpdateSelectionOnRootLineBoxes()) {
if (is<RenderText>(renderer))
- m_rect = downcast<RenderText>(renderer).collectSelectionGeometriesForLineBoxes(m_repaintContainer, clipToVisibleContent, m_collectedSelectionRects);
+ m_rect = downcast<RenderText>(renderer).collectSelectionGeometriesForLineBoxes(m_repaintContainer, clipToVisibleContent, m_collectedSelectionQuads);
else
m_rect = renderer.selectionRectForRepaint(m_repaintContainer, clipToVisibleContent);
}
Modified: trunk/Source/WebCore/rendering/RenderSelectionInfo.h (277273 => 277274)
--- trunk/Source/WebCore/rendering/RenderSelectionInfo.h 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/RenderSelectionInfo.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -53,11 +53,11 @@
RenderSelectionInfo(RenderObject& renderer, bool clipToVisibleContent);
void repaint();
- const Vector<LayoutRect>& collectedSelectionRects() const { return m_collectedSelectionRects; }
+ const Vector<FloatQuad>& collectedSelectionQuads() const { return m_collectedSelectionQuads; }
LayoutRect rect() const { return m_rect; }
private:
- Vector<LayoutRect> m_collectedSelectionRects; // relative to repaint container
+ Vector<FloatQuad> m_collectedSelectionQuads; // relative to repaint container
LayoutRect m_rect; // relative to repaint container
};
Modified: trunk/Source/WebCore/rendering/RenderText.cpp (277273 => 277274)
--- trunk/Source/WebCore/rendering/RenderText.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/RenderText.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -1593,7 +1593,7 @@
return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
}
-LayoutRect RenderText::collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>* rects)
+LayoutRect RenderText::collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<FloatQuad>* quads)
{
ASSERT(!needsLayout());
@@ -1633,8 +1633,8 @@
resultRect.unite(rect);
- if (rects)
- rects->append(localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox());
+ if (quads)
+ quads->append(localToContainerQuad(FloatRect(rect), repaintContainer));
}
if (clipToVisibleContent)
@@ -1642,9 +1642,9 @@
return localToContainerQuad(FloatRect(resultRect), repaintContainer).enclosingBoundingBox();
}
-LayoutRect RenderText::collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>& rects)
+LayoutRect RenderText::collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<FloatQuad>& quads)
{
- return collectSelectionGeometriesForLineBoxes(repaintContainer, clipToVisibleContent, &rects);
+ return collectSelectionGeometriesForLineBoxes(repaintContainer, clipToVisibleContent, &quads);
}
LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
Modified: trunk/Source/WebCore/rendering/RenderText.h (277273 => 277274)
--- trunk/Source/WebCore/rendering/RenderText.h 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/RenderText.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -126,7 +126,7 @@
bool canBeSelectionLeaf() const override { return true; }
- LayoutRect collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>&);
+ LayoutRect collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<FloatQuad>&);
LayoutUnit marginLeft() const { return minimumValueForLength(style().marginLeft(), 0); }
LayoutUnit marginRight() const { return minimumValueForLength(style().marginRight(), 0); }
@@ -215,7 +215,7 @@
void secureText(UChar mask);
- LayoutRect collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<LayoutRect>*);
+ LayoutRect collectSelectionGeometriesForLineBoxes(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent, Vector<FloatQuad>*);
bool computeCanUseSimplifiedTextMeasuring() const;
void node() const = delete;
Modified: trunk/Source/WebCore/rendering/SelectionRangeData.cpp (277273 => 277274)
--- trunk/Source/WebCore/rendering/SelectionRangeData.cpp 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/SelectionRangeData.cpp 2021-05-10 18:10:03 UTC (rev 277274)
@@ -110,7 +110,7 @@
SelectionRangeData::SelectionRangeData(RenderView& view)
: m_renderView(view)
#if ENABLE(SERVICE_CONTROLS)
- , m_selectionRectGatherer(view)
+ , m_selectionGeometryGatherer(view)
#endif
{
}
@@ -126,7 +126,7 @@
#if ENABLE(SERVICE_CONTROLS)
// Clear the current rects and create a notifier for the new rects we are about to gather.
// The Notifier updates the Editor when it goes out of scope and is destroyed.
- auto rectNotifier = m_selectionRectGatherer.clearAndCreateNotifier();
+ auto notifier = m_selectionGeometryGatherer.clearAndCreateNotifier();
#endif
m_selectionWasCaret = isCaret;
apply(selection, blockRepaintMode);
@@ -256,10 +256,10 @@
if (isValidRendererForSelection(*currentRenderer, m_renderRange)) {
std::unique_ptr<RenderSelectionInfo> selectionInfo = makeUnique<RenderSelectionInfo>(*currentRenderer, true);
#if ENABLE(SERVICE_CONTROLS)
- for (auto& rect : selectionInfo->collectedSelectionRects())
- m_selectionRectGatherer.addRect(selectionInfo->repaintContainer(), rect);
+ for (auto& quad : selectionInfo->collectedSelectionQuads())
+ m_selectionGeometryGatherer.addQuad(selectionInfo->repaintContainer(), quad);
if (!currentRenderer->isTextOrLineBreak())
- m_selectionRectGatherer.setTextOnly(false);
+ m_selectionGeometryGatherer.setTextOnly(false);
#endif
newSelectedRenderers.set(currentRenderer, WTFMove(selectionInfo));
auto* containingBlock = currentRenderer->containingBlock();
@@ -270,7 +270,7 @@
blockInfo = makeUnique<RenderBlockSelectionInfo>(*containingBlock);
containingBlock = containingBlock->containingBlock();
#if ENABLE(SERVICE_CONTROLS)
- m_selectionRectGatherer.addGapRects(blockInfo->repaintContainer(), blockInfo->rects());
+ m_selectionGeometryGatherer.addGapRects(blockInfo->repaintContainer(), blockInfo->rects());
#endif
}
}
Modified: trunk/Source/WebCore/rendering/SelectionRangeData.h (277273 => 277274)
--- trunk/Source/WebCore/rendering/SelectionRangeData.h 2021-05-10 18:06:03 UTC (rev 277273)
+++ trunk/Source/WebCore/rendering/SelectionRangeData.h 2021-05-10 18:10:03 UTC (rev 277274)
@@ -33,7 +33,7 @@
#include "RenderSelectionInfo.h"
#if ENABLE(SERVICE_CONTROLS)
-#include "SelectionRectGatherer.h"
+#include "SelectionGeometryGatherer.h"
#endif
namespace WebCore {
@@ -53,7 +53,7 @@
private:
const RenderView& m_renderView;
#if ENABLE(SERVICE_CONTROLS)
- SelectionRectGatherer m_selectionRectGatherer;
+ SelectionGeometryGatherer m_selectionGeometryGatherer;
#endif
bool m_selectionWasCaret { false };
enum class ClipToVisibleContent { Yes, No };