Add TextIndicator support for providing a snapshot excluding selected content
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Mar 2017 01:44:45 +0000 (01:44 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Mar 2017 01:44:45 +0000 (01:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169309
<rdar://problem/30883525>

Reviewed by Tim Horton.

Source/WebCore:

Work towards <rdar://problem/30882974>. Adds support in TextIndicator to include a snapshot of all visible
content, excluding nodes captured in the current selection. This comes in the form of the new
TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection flag -- see per-method changes for more details.

No new tests, since there is no change in behavior yet.

* page/FrameSnapshotting.cpp:
(WebCore::snapshotFrameRectWithClip):
* page/FrameSnapshotting.h:

Introduce a new snapshot option flag, SnapshotOptionsPaintEverythingExcludingSelection.

(WebCore::snapshotFrameRectWithClip):
* page/TextIndicator.cpp:

If TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection is turned on, capture and include a
snapshot of the visible bounds of the frame.

(WebCore::takeSnapshot):
(WebCore::takeSnapshots):
(WebCore::initializeIndicator):
* page/TextIndicator.h:

Introduce TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection.

* platform/graphics/FontCascade.cpp:
(WebCore::FontCascade::widthOfTextRange):
* platform/graphics/FontCascade.h:

Teach FontCascade to retrieve the width of a range in a TextRun, and also compute the widths of the TextRun
before and after the range. This is used by InlineTextBox to compute the painting rect to clip out when skipping
text decorations for the selected region of the TextRun.

* rendering/InlineTextBox.cpp:

Teach InlineTextBox to respect PaintBehaviorExcludeSelection. When painting text, if this paint behavior is
used, we will not paint the portion of the text run that lies inside the range determined by selectionStartEnd().
Similarly, when painting text decorations, we exclude the rect surrounding the selected content.

(WebCore::InlineTextBox::paint):
(WebCore::InlineTextBox::paintDecoration):
* rendering/InlineTextBox.h:
* rendering/PaintPhase.h:

Introduce PaintBehaviorExcludeSelection, used to inform members of the render tree not to paint portions that
lie within the current selection range.

* rendering/RenderLayer.cpp:

Propagate the PaintBehaviorExcludeSelection flag to children when painting.

(WebCore::RenderLayer::paintLayerContents):
(WebCore::RenderLayer::paintForegroundForFragments):
* rendering/RenderReplaced.cpp:
(WebCore::RenderReplaced::shouldPaint):

Teach RenderReplaced to respect PaintBehaviorExcludeSelection by bailing from painting if it is selected and the
paint behavior is enabled.

* rendering/TextDecorationPainter.h:
* rendering/TextPaintStyle.cpp:
(WebCore::computeTextSelectionPaintStyle):
* rendering/TextPaintStyle.h:
* rendering/TextPainter.cpp:
(WebCore::TextPainter::paintText):
* rendering/TextPainter.h:

Source/WebKit2:

Serialize the snapshot excluding the selection and the snapshot's bounds when sending TextIndicatorData over
IPC to the UI process.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<TextIndicatorData>::encode):
(IPC::ArgumentCoder<TextIndicatorData>::decode):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213614 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/FrameSnapshotting.cpp
Source/WebCore/page/FrameSnapshotting.h
Source/WebCore/page/TextIndicator.cpp
Source/WebCore/page/TextIndicator.h
Source/WebCore/platform/graphics/FontCascade.cpp
Source/WebCore/platform/graphics/FontCascade.h
Source/WebCore/rendering/InlineTextBox.cpp
Source/WebCore/rendering/InlineTextBox.h
Source/WebCore/rendering/PaintPhase.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderReplaced.cpp
Source/WebCore/rendering/TextDecorationPainter.h
Source/WebCore/rendering/TextPaintStyle.cpp
Source/WebCore/rendering/TextPaintStyle.h
Source/WebCore/rendering/TextPainter.cpp
Source/WebCore/rendering/TextPainter.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp

index 48e82820c73c4f2e72af9c1dfac736bf60a9c58a..52a1a9e92a32be24bb0b2d240d3426e8d0e2b3d2 100644 (file)
@@ -1,3 +1,78 @@
+2017-03-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Add TextIndicator support for providing a snapshot excluding selected content
+        https://bugs.webkit.org/show_bug.cgi?id=169309
+        <rdar://problem/30883525>
+
+        Reviewed by Tim Horton.
+
+        Work towards <rdar://problem/30882974>. Adds support in TextIndicator to include a snapshot of all visible
+        content, excluding nodes captured in the current selection. This comes in the form of the new
+        TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection flag -- see per-method changes for more details.
+
+        No new tests, since there is no change in behavior yet.
+
+        * page/FrameSnapshotting.cpp:
+        (WebCore::snapshotFrameRectWithClip):
+        * page/FrameSnapshotting.h:
+
+        Introduce a new snapshot option flag, SnapshotOptionsPaintEverythingExcludingSelection.
+
+        (WebCore::snapshotFrameRectWithClip):
+        * page/TextIndicator.cpp:
+
+        If TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection is turned on, capture and include a
+        snapshot of the visible bounds of the frame.
+
+        (WebCore::takeSnapshot):
+        (WebCore::takeSnapshots):
+        (WebCore::initializeIndicator):
+        * page/TextIndicator.h:
+
+        Introduce TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection.
+
+        * platform/graphics/FontCascade.cpp:
+        (WebCore::FontCascade::widthOfTextRange):
+        * platform/graphics/FontCascade.h:
+
+        Teach FontCascade to retrieve the width of a range in a TextRun, and also compute the widths of the TextRun
+        before and after the range. This is used by InlineTextBox to compute the painting rect to clip out when skipping
+        text decorations for the selected region of the TextRun.
+
+        * rendering/InlineTextBox.cpp:
+
+        Teach InlineTextBox to respect PaintBehaviorExcludeSelection. When painting text, if this paint behavior is
+        used, we will not paint the portion of the text run that lies inside the range determined by selectionStartEnd().
+        Similarly, when painting text decorations, we exclude the rect surrounding the selected content.
+
+        (WebCore::InlineTextBox::paint):
+        (WebCore::InlineTextBox::paintDecoration):
+        * rendering/InlineTextBox.h:
+        * rendering/PaintPhase.h:
+
+        Introduce PaintBehaviorExcludeSelection, used to inform members of the render tree not to paint portions that
+        lie within the current selection range.
+
+        * rendering/RenderLayer.cpp:
+
+        Propagate the PaintBehaviorExcludeSelection flag to children when painting.
+
+        (WebCore::RenderLayer::paintLayerContents):
+        (WebCore::RenderLayer::paintForegroundForFragments):
+        * rendering/RenderReplaced.cpp:
+        (WebCore::RenderReplaced::shouldPaint):
+
+        Teach RenderReplaced to respect PaintBehaviorExcludeSelection by bailing from painting if it is selected and the
+        paint behavior is enabled.
+
+        * rendering/TextDecorationPainter.h:
+        * rendering/TextPaintStyle.cpp:
+        (WebCore::computeTextSelectionPaintStyle):
+        * rendering/TextPaintStyle.h:
+        * rendering/TextPainter.cpp:
+        (WebCore::TextPainter::paintText):
+        * rendering/TextPainter.h:
+
 2017-03-08  Youenn Fablet  <youenn@apple.com>
 
         Support PeerConnectionStates::BundlePolicy::MaxBundle when setting rtc configuration
index 3d34cd9291fe81ceff3357a04aae4e7cc1ac4002..959c362a9ca6a383dbe273e030de1dfa8540172c 100644 (file)
@@ -73,7 +73,7 @@ std::unique_ptr<ImageBuffer> snapshotFrameRect(Frame& frame, const IntRect& imag
     return snapshotFrameRectWithClip(frame, imageRect, clipRects, options);
 }
 
-std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& imageRect, Vector<FloatRect>& clipRects, SnapshotOptions options)
+std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& imageRect, const Vector<FloatRect>& clipRects, SnapshotOptions options)
 {
     if (!frame.page())
         return nullptr;
@@ -97,6 +97,8 @@ std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRe
         paintBehavior |= PaintBehaviorSelectionOnly;
     if (options & SnapshotOptionsPaintSelectionAndBackgroundsOnly)
         paintBehavior |= PaintBehaviorSelectionAndBackgroundsOnly;
+    if (options & SnapshotOptionsPaintEverythingExcludingSelection)
+        paintBehavior |= PaintBehaviorExcludeSelection;
 
     // Other paint behaviors are set by paintContentsForSnapshot.
     frame.view()->setPaintBehavior(paintBehavior);
index dc6356886e445f7dccdcecb5430c92cdbbb158ba..fb3dd03f9327692ebb4e8de874a606a7da73836d 100644 (file)
@@ -47,11 +47,12 @@ enum {
     SnapshotOptionsInViewCoordinates = 1 << 2,
     SnapshotOptionsForceBlackText = 1 << 3,
     SnapshotOptionsPaintSelectionAndBackgroundsOnly = 1 << 4,
+    SnapshotOptionsPaintEverythingExcludingSelection = 1 << 5
 };
 typedef unsigned SnapshotOptions;
 
 WEBCORE_EXPORT std::unique_ptr<ImageBuffer> snapshotFrameRect(Frame&, const IntRect&, SnapshotOptions = SnapshotOptionsNone);
-std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame&, const IntRect&, Vector<FloatRect>& clipRects, SnapshotOptions = SnapshotOptionsNone);
+std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame&, const IntRect&, const Vector<FloatRect>& clipRects = { }, SnapshotOptions = SnapshotOptionsNone);
 std::unique_ptr<ImageBuffer> snapshotNode(Frame&, Node&);
 WEBCORE_EXPORT std::unique_ptr<ImageBuffer> snapshotSelection(Frame&, SnapshotOptions = SnapshotOptionsNone);
 
index ea90bf74b9ca76efadb3ae443877ac6209bf2edb..f1baea78635fe037b20e59f7a6b36996f5130532 100644 (file)
@@ -150,7 +150,7 @@ static SnapshotOptions snapshotOptionsForTextIndicatorOptions(TextIndicatorOptio
     return snapshotOptions;
 }
 
-static RefPtr<Image> takeSnapshot(Frame& frame, IntRect rect, SnapshotOptions options, float& scaleFactor, Vector<FloatRect>& clipRectsInDocumentCoordinates)
+static RefPtr<Image> takeSnapshot(Frame& frame, IntRect rect, SnapshotOptions options, float& scaleFactor, const Vector<FloatRect>& clipRectsInDocumentCoordinates)
 {
     std::unique_ptr<ImageBuffer> buffer = snapshotFrameRectWithClip(frame, rect, clipRectsInDocumentCoordinates, options);
     if (!buffer)
@@ -159,7 +159,7 @@ static RefPtr<Image> takeSnapshot(Frame& frame, IntRect rect, SnapshotOptions op
     return ImageBuffer::sinkIntoImage(WTFMove(buffer), Unscaled);
 }
 
-static bool takeSnapshots(TextIndicatorData& data, Frame& frame, IntRect snapshotRect, Vector<FloatRect>& clipRectsInDocumentCoordinates)
+static bool takeSnapshots(TextIndicatorData& data, Frame& frame, IntRect snapshotRect, const Vector<FloatRect>& clipRectsInDocumentCoordinates)
 {
     SnapshotOptions snapshotOptions = snapshotOptionsForTextIndicatorOptions(data.options);
 
@@ -172,6 +172,13 @@ static bool takeSnapshots(TextIndicatorData& data, Frame& frame, IntRect snapsho
         data.contentImageWithHighlight = takeSnapshot(frame, snapshotRect, SnapshotOptionsNone, snapshotScaleFactor, clipRectsInDocumentCoordinates);
         ASSERT(!data.contentImageWithHighlight || data.contentImageScaleFactor == snapshotScaleFactor);
     }
+
+    if (data.options & TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection) {
+        float snapshotScaleFactor;
+        auto snapshotRect = enclosingIntRect(frame.view()->visualViewportRect());
+        data.contentImageWithoutSelection = takeSnapshot(frame, snapshotRect, SnapshotOptionsPaintEverythingExcludingSelection, snapshotScaleFactor, { });
+        data.contentImageWithoutSelectionRectInRootViewCoordinates = frame.view()->contentsToRootView(snapshotRect);
+    }
     
     return true;
 }
index dfa42c7dc422eebbc50e5583a50ac0f235ffa85d..a8e2d1976adc38f952bae3a5213b825c35d28ab2 100644 (file)
@@ -49,7 +49,7 @@ enum class TextIndicatorPresentationTransition {
 };
 
 // Make sure to keep these in sync with the ones in Internals.idl.
-enum TextIndicatorOption : uint8_t {
+enum TextIndicatorOption : uint16_t {
     TextIndicatorOptionDefault = 0,
 
     // Use the styled text color instead of forcing black text (the default)
@@ -80,15 +80,20 @@ enum TextIndicatorOption : uint8_t {
     // By default, TextIndicator clips the indicated rects to the visible content rect.
     // If this option is set, do not clip the indicated rects.
     TextIndicatorOptionDoNotClipToVisibleRect = 1 << 7,
+
+    // Include an additional snapshot of everything in view, with the exception of nodes within the currently selected range.
+    TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection = 1 << 8,
 };
-typedef uint8_t TextIndicatorOptions;
+typedef uint16_t TextIndicatorOptions;
 
 struct TextIndicatorData {
     FloatRect selectionRectInRootViewCoordinates;
     FloatRect textBoundingRectInRootViewCoordinates;
+    FloatRect contentImageWithoutSelectionRectInRootViewCoordinates;
     Vector<FloatRect> textRectsInBoundingRectCoordinates;
     float contentImageScaleFactor;
     RefPtr<Image> contentImageWithHighlight;
+    RefPtr<Image> contentImageWithoutSelection;
     RefPtr<Image> contentImage;
     TextIndicatorPresentationTransition presentationTransition;
     TextIndicatorOptions options;
index 66413884a5e2c388ccd75171fda3cb599520067b..483e41cb14ab67ce413ac7395fb7404ba7f9adce 100644 (file)
@@ -25,6 +25,7 @@
 #include "FontCascade.h"
 
 #include "CharacterProperties.h"
+#include "ComplexTextController.h"
 #include "FloatRect.h"
 #include "FontCache.h"
 #include "GlyphBuffer.h"
@@ -348,6 +349,43 @@ void FontCascade::drawEmphasisMarks(GraphicsContext& context, const TextRun& run
         drawEmphasisMarksForComplexText(context, run, mark, point, from, destination);
 }
 
+float FontCascade::widthOfTextRange(const TextRun& run, unsigned from, unsigned to, HashSet<const Font*>* fallbackFonts, float* outWidthBeforeRange, float* outWidthAfterRange) const
+{
+    ASSERT(from <= to);
+    ASSERT(to <= run.length());
+
+    float offsetBeforeRange = 0;
+    float offsetAfterRange = 0;
+    float totalWidth = 0;
+
+    auto codePathToUse = codePath(run);
+    if (codePathToUse == Complex) {
+        ComplexTextController complexIterator(*this, run, false, fallbackFonts);
+        complexIterator.advance(from, nullptr, IncludePartialGlyphs, fallbackFonts);
+        offsetBeforeRange = complexIterator.runWidthSoFar();
+        complexIterator.advance(to, nullptr, IncludePartialGlyphs, fallbackFonts);
+        offsetAfterRange = complexIterator.runWidthSoFar();
+        complexIterator.advance(run.length(), nullptr, IncludePartialGlyphs, fallbackFonts);
+        totalWidth = complexIterator.runWidthSoFar();
+    } else {
+        WidthIterator simpleIterator(this, run, fallbackFonts);
+        simpleIterator.advance(from, nullptr);
+        offsetBeforeRange = simpleIterator.runWidthSoFar();
+        simpleIterator.advance(to, nullptr);
+        offsetAfterRange = simpleIterator.runWidthSoFar();
+        simpleIterator.advance(run.length(), nullptr);
+        totalWidth = simpleIterator.runWidthSoFar();
+    }
+
+    if (outWidthBeforeRange)
+        *outWidthBeforeRange = offsetBeforeRange;
+
+    if (outWidthAfterRange)
+        *outWidthAfterRange = totalWidth - offsetAfterRange;
+
+    return offsetAfterRange - offsetBeforeRange;
+}
+
 float FontCascade::width(const TextRun& run, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
 {
     CodePath codePathToUse = codePath(run);
index 3762e481527dd6cc50c272a1caeb290895b6aff6..9424995099b0dd3c6d0745f9f76c40ccdab069bf 100644 (file)
@@ -138,6 +138,7 @@ public:
 
     DashArray dashesForIntersectionsWithRect(const TextRun&, const FloatPoint& textOrigin, const FloatRect& lineExtents) const;
 
+    float widthOfTextRange(const TextRun&, unsigned from, unsigned to, HashSet<const Font*>* fallbackFonts = 0, float* outWidthBeforeRange = nullptr, float* outWidthAfterRange = nullptr) const;
     WEBCORE_EXPORT float width(const TextRun&, HashSet<const Font*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
     float widthForSimpleText(StringView text) const;
 
index f6f248af33a216472adc354e018a4ddd00b8c71a..1ecb7dfe3d58e22da0df785f66b3097e0e3c6e1a 100644 (file)
@@ -474,10 +474,11 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
 
     bool paintSelectedTextOnly = false;
     bool paintSelectedTextSeparately = false;
+    bool paintNonSelectedTextOnly = false;
     const ShadowData* selectionShadow = nullptr;
     
     // Text with custom underlines does not have selection background painted, so selection paint style is not appropriate for it.
-    TextPaintStyle selectionPaintStyle = haveSelection && !useCustomUnderlines ? computeTextSelectionPaintStyle(textPaintStyle, renderer(), lineStyle, paintInfo, paintSelectedTextOnly, paintSelectedTextSeparately, selectionShadow) : textPaintStyle;
+    TextPaintStyle selectionPaintStyle = haveSelection && !useCustomUnderlines ? computeTextSelectionPaintStyle(textPaintStyle, renderer(), lineStyle, paintInfo, paintSelectedTextOnly, paintSelectedTextSeparately, paintNonSelectedTextOnly, selectionShadow) : textPaintStyle;
 
     // Set our font.
     const FontCascade& font = fontToUse(lineStyle, renderer());
@@ -551,12 +552,32 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
     textPainter.addTextShadow(textShadow, selectionShadow);
     textPainter.addEmphasis(emphasisMark, emphasisMarkOffset, combinedText);
 
-    textPainter.paintText(textRun, length, boxRect, textOrigin, selectionStart, selectionEnd, paintSelectedTextOnly, paintSelectedTextSeparately);
+    textPainter.paintText(textRun, length, boxRect, textOrigin, selectionStart, selectionEnd, paintSelectedTextOnly, paintSelectedTextSeparately, paintNonSelectedTextOnly);
 
     // Paint decorations
     TextDecoration textDecorations = lineStyle.textDecorationsInEffect();
-    if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection)
-        paintDecoration(context, font, combinedText, textRun, textOrigin, boxRect, textDecorations, textPaintStyle, textShadow);
+    if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection) {
+        FloatRect textDecorationSelectionClipOutRect;
+        if ((paintInfo.paintBehavior & PaintBehaviorExcludeSelection) && selectionStart < selectionEnd && selectionEnd <= length) {
+            textDecorationSelectionClipOutRect = logicalOverflowRect();
+            textDecorationSelectionClipOutRect.moveBy(localPaintOffset);
+            float logicalWidthBeforeRange;
+            float logicalWidthAfterRange;
+            float logicalSelectionWidth = font.widthOfTextRange(textRun, selectionStart, selectionEnd, nullptr, &logicalWidthBeforeRange, &logicalWidthAfterRange);
+            // FIXME: Do we need to handle vertical bottom to top text?
+            if (!isHorizontal()) {
+                textDecorationSelectionClipOutRect.move(0, logicalWidthBeforeRange);
+                textDecorationSelectionClipOutRect.setHeight(logicalSelectionWidth);
+            } else if (direction() == RTL) {
+                textDecorationSelectionClipOutRect.move(logicalWidthAfterRange, 0);
+                textDecorationSelectionClipOutRect.setWidth(logicalSelectionWidth);
+            } else {
+                textDecorationSelectionClipOutRect.move(logicalWidthBeforeRange, 0);
+                textDecorationSelectionClipOutRect.setWidth(logicalSelectionWidth);
+            }
+        }
+        paintDecoration(context, font, combinedText, textRun, textOrigin, boxRect, textDecorations, textPaintStyle, textShadow, textDecorationSelectionClipOutRect);
+    }
 
     if (paintInfo.phase == PaintPhaseForeground) {
         paintDocumentMarkers(context, boxOrigin, lineStyle, font, false);
@@ -695,7 +716,7 @@ static inline void mirrorRTLSegment(float logicalWidth, TextDirection direction,
 }
 
 void InlineTextBox::paintDecoration(GraphicsContext& context, const FontCascade& font, RenderCombineText* combinedText, const TextRun& textRun, const FloatPoint& textOrigin,
-    const FloatRect& boxRect, TextDecoration decoration, TextPaintStyle textPaintStyle, const ShadowData* shadow)
+    const FloatRect& boxRect, TextDecoration decoration, TextPaintStyle textPaintStyle, const ShadowData* shadow, const FloatRect& clipOutRect)
 {
     if (m_truncation == cFullTruncation)
         return;
@@ -721,8 +742,17 @@ void InlineTextBox::paintDecoration(GraphicsContext& context, const FontCascade&
 
     FloatPoint localOrigin = boxRect.location();
     localOrigin.move(start, 0);
+
+    if (!clipOutRect.isEmpty()) {
+        context.save();
+        context.clipOut(clipOutRect);
+    }
+
     decorationPainter.paintTextDecoration(textRun, textOrigin, localOrigin);
 
+    if (!clipOutRect.isEmpty())
+        context.restore();
+
     if (combinedText)
         context.concatCTM(rotation(boxRect, Counterclockwise));
 }
index 9c4618a16748f14d285ecd715cf5af80ec64f2b4..4f19c9ddd8e9172d74dafb75592fc91b100eef6d 100644 (file)
@@ -159,7 +159,7 @@ protected:
 
 private:
     void paintDecoration(GraphicsContext&, const FontCascade&, RenderCombineText*, const TextRun&, const FloatPoint& textOrigin, const FloatRect& boxRect,
-        TextDecoration, TextPaintStyle, const ShadowData*);
+        TextDecoration, TextPaintStyle, const ShadowData*, const FloatRect& clipOutRect);
     void paintSelection(GraphicsContext&, const FloatPoint& boxOrigin, const RenderStyle&, const FontCascade&, const Color& textColor);
     void paintDocumentMarker(GraphicsContext&, const FloatPoint& boxOrigin, RenderedDocumentMarker&, const RenderStyle&, const FontCascade&, bool grammar);
     void paintTextMatchMarker(GraphicsContext&, const FloatPoint& boxOrigin, RenderedDocumentMarker&, const RenderStyle&, const FontCascade&);
index 49fb7dff8a77760278c83731ec1670f085f5bd27..f167e87a8e022122cdff04d6b668a7c9c209d316 100644 (file)
@@ -63,6 +63,7 @@ enum PaintBehaviorFlags {
     PaintBehaviorSkipRootBackground          = 1 << 6,
     PaintBehaviorRootBackgroundOnly          = 1 << 7,
     PaintBehaviorSelectionAndBackgroundsOnly = 1 << 8,
+    PaintBehaviorExcludeSelection            = 1 << 9,
 };
 
 typedef unsigned PaintBehavior;
index 49ca5f4de256fdbb299814bbe85bb6d8080e732e..8f3e34e3bc73a49c130e661f4a447fc61cf99236 100644 (file)
@@ -4375,6 +4375,9 @@ void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPainti
         else if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly)
             paintBehavior |= PaintBehaviorRootBackgroundOnly;
 
+        if (paintingInfo.paintBehavior & PaintBehaviorExcludeSelection)
+            paintBehavior |= PaintBehaviorExcludeSelection;
+
         LayoutRect paintDirtyRect = localPaintingInfo.paintDirtyRect;
         if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
             // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
@@ -4771,6 +4774,9 @@ void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragmen
     else
         localPaintBehavior = paintBehavior;
 
+    if (localPaintingInfo.paintBehavior & PaintBehaviorExcludeSelection)
+        localPaintBehavior |= PaintBehaviorExcludeSelection;
+
     // Optimize clipping for the single fragment case.
     bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
     ClipRect clippedRect;
index 683e00fb249bbfc846836e08d46aa8af8da9615c..f9a20e99169bedb98efba9240ed62ee89cf875ea 100644 (file)
@@ -205,6 +205,9 @@ void RenderReplaced::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 
 bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
+    if ((paintInfo.paintBehavior & PaintBehaviorExcludeSelection) && isSelected())
+        return false;
+
     if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseOutline && paintInfo.phase != PaintPhaseSelfOutline 
             && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseMask)
         return false;
index 4e95587be799df3887816740ad5cec7377459ce0..6e2ca8d5480ceb7e3ccc0b1f7b6cf137cc57587f 100644 (file)
@@ -29,6 +29,7 @@
 namespace WebCore {
 
 class FontCascade;
+class FloatRect;
 class GraphicsContext;
 class InlineTextBox;
 class RenderObject;
index 5756da0fb662e12f9f2f1458accc4166e0f87ce2..42360df357d1360a4abfa0adb81bdabb409558f2 100644 (file)
@@ -116,10 +116,11 @@ TextPaintStyle computeTextPaintStyle(const Frame& frame, const RenderStyle& line
     return paintStyle;
 }
 
-TextPaintStyle computeTextSelectionPaintStyle(const TextPaintStyle& textPaintStyle, const RenderText& renderer, const RenderStyle& lineStyle, const PaintInfo& paintInfo, bool& paintSelectedTextOnly, bool& paintSelectedTextSeparately, const ShadowData*& selectionShadow)
+TextPaintStyle computeTextSelectionPaintStyle(const TextPaintStyle& textPaintStyle, const RenderText& renderer, const RenderStyle& lineStyle, const PaintInfo& paintInfo, bool& paintSelectedTextOnly, bool& paintSelectedTextSeparately, bool& paintNonSelectedTextOnly, const ShadowData*& selectionShadow)
 {
     paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
-    paintSelectedTextSeparately = false;
+    paintSelectedTextSeparately = paintInfo.paintBehavior & PaintBehaviorExcludeSelection;
+    paintNonSelectedTextOnly = paintInfo.paintBehavior & PaintBehaviorExcludeSelection;
     selectionShadow = (paintInfo.forceTextColor()) ? nullptr : lineStyle.textShadow();
 
     TextPaintStyle selectionPaintStyle = textPaintStyle;
index 3e8be27f262717164d0d98e6103a9ad2d0fa7a65..df2171ae2c969702e6596bf59c6927709508ec5c 100644 (file)
@@ -55,7 +55,7 @@ struct TextPaintStyle {
 };
 
 TextPaintStyle computeTextPaintStyle(const Frame&, const RenderStyle&, const PaintInfo&);
-TextPaintStyle computeTextSelectionPaintStyle(const TextPaintStyle&, const RenderText&, const RenderStyle&, const PaintInfo&, bool& paintSelectedTextOnly, bool& paintSelectedTextSeparately, const ShadowData*& selectionShadow);
+TextPaintStyle computeTextSelectionPaintStyle(const TextPaintStyle&, const RenderText&, const RenderStyle&, const PaintInfo&, bool& paintSelectedTextOnly, bool& paintSelectedTextSeparately, bool& paintNonSelectedTextOnly, const ShadowData*& selectionShadow);
 
 enum FillColorType { UseNormalFillColor, UseEmphasisMarkColor };
 void updateGraphicsContext(GraphicsContext&, const TextPaintStyle&, FillColorType = UseNormalFillColor);
index a835e6768db7b2fdd86e7bc95ae7824e71c773b1..affffa4f6e968baad8135e60041a01033965e1ed 100644 (file)
@@ -170,7 +170,7 @@ void TextPainter::paintTextAndEmphasisMarksIfNeeded(const TextRun& textRun, cons
 }
     
 void TextPainter::paintText(const TextRun& textRun, unsigned length, const FloatRect& boxRect, const FloatPoint& textOrigin, unsigned selectionStart, unsigned selectionEnd,
-    bool paintSelectedTextOnly, bool paintSelectedTextSeparately)
+    bool paintSelectedTextOnly, bool paintSelectedTextSeparately, bool paintNonSelectedTextOnly)
 {
     ASSERT(m_font);
     if (!paintSelectedTextOnly) {
@@ -189,6 +189,10 @@ void TextPainter::paintText(const TextRun& textRun, unsigned length, const Float
                 paintTextAndEmphasisMarksIfNeeded(textRun, boxRect, textOrigin, selectionEnd, length, m_textPaintStyle, m_textShadow);
         }
     }
+
+    if (paintNonSelectedTextOnly)
+        return;
+
     // Paint only the text that is selected.
     if ((paintSelectedTextOnly || paintSelectedTextSeparately) && selectionStart < selectionEnd) {
         GraphicsContextStateSaver stateSaver(m_context, m_selectionPaintStyle.strokeWidth > 0);
index 6ac04014280d40a4c21736cdfe47c6f789f6816f..d9536c700e8302b4d3293589d69d35a1e716274e 100644 (file)
@@ -57,7 +57,7 @@ public:
     void addTextShadow(const ShadowData* textShadow, const ShadowData* selectionShadow);
 
     void paintText(const TextRun&, unsigned length, const FloatRect& boxRect, const FloatPoint& textOrigin,
-        unsigned selectionStart = 0, unsigned selectionEnd = 0, bool paintSelectedTextOnly = false, bool paintSelectedTextSeparately = false);
+        unsigned selectionStart = 0, unsigned selectionEnd = 0, bool paintSelectedTextOnly = false, bool paintSelectedTextSeparately = false, bool paintNonSelectedTextOnly = false);
 
 private:
     void drawTextOrEmphasisMarks(const FontCascade&, const TextRun&, const AtomicString& emphasisMark, float emphasisMarkOffset,
index 01de5de8fbae6d79cd4e639182c634fbd74ad655..7dca5d867415817eec85e28f22526e578ef31238 100644 (file)
@@ -1,3 +1,18 @@
+2017-03-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Add TextIndicator support for providing a snapshot excluding selected content
+        https://bugs.webkit.org/show_bug.cgi?id=169309
+        <rdar://problem/30883525>
+
+        Reviewed by Tim Horton.
+
+        Serialize the snapshot excluding the selection and the snapshot's bounds when sending TextIndicatorData over
+        IPC to the UI process.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<TextIndicatorData>::encode):
+        (IPC::ArgumentCoder<TextIndicatorData>::decode):
+
 2017-03-08  Brent Fulgham  <bfulgham@apple.com>
 
         REGRESSION(r213564): Netflix does not play content
index 6166ab6ea151619cd97af1b73b6a495ae7098f2c..84ccf8f49b444c3439fb65aade0b78f69ea81ffb 100644 (file)
@@ -2082,12 +2082,14 @@ void ArgumentCoder<TextIndicatorData>::encode(Encoder& encoder, const TextIndica
     encoder << textIndicatorData.selectionRectInRootViewCoordinates;
     encoder << textIndicatorData.textBoundingRectInRootViewCoordinates;
     encoder << textIndicatorData.textRectsInBoundingRectCoordinates;
+    encoder << textIndicatorData.contentImageWithoutSelectionRectInRootViewCoordinates;
     encoder << textIndicatorData.contentImageScaleFactor;
     encoder.encodeEnum(textIndicatorData.presentationTransition);
     encoder << static_cast<uint64_t>(textIndicatorData.options);
 
     encodeOptionalImage(encoder, textIndicatorData.contentImage.get());
     encodeOptionalImage(encoder, textIndicatorData.contentImageWithHighlight.get());
+    encodeOptionalImage(encoder, textIndicatorData.contentImageWithoutSelection.get());
 }
 
 bool ArgumentCoder<TextIndicatorData>::decode(Decoder& decoder, TextIndicatorData& textIndicatorData)
@@ -2101,6 +2103,9 @@ bool ArgumentCoder<TextIndicatorData>::decode(Decoder& decoder, TextIndicatorDat
     if (!decoder.decode(textIndicatorData.textRectsInBoundingRectCoordinates))
         return false;
 
+    if (!decoder.decode(textIndicatorData.contentImageWithoutSelectionRectInRootViewCoordinates))
+        return false;
+
     if (!decoder.decode(textIndicatorData.contentImageScaleFactor))
         return false;
 
@@ -2118,6 +2123,9 @@ bool ArgumentCoder<TextIndicatorData>::decode(Decoder& decoder, TextIndicatorDat
     if (!decodeOptionalImage(decoder, textIndicatorData.contentImageWithHighlight))
         return false;
 
+    if (!decodeOptionalImage(decoder, textIndicatorData.contentImageWithoutSelection))
+        return false;
+
     return true;
 }