Title: [237893] trunk
Revision
237893
Author
mmaxfi...@apple.com
Date
2018-11-06 15:06:37 -0800 (Tue, 06 Nov 2018)

Log Message

Spelling dots are drawn in the wrong place
https://bugs.webkit.org/show_bug.cgi?id=190764

Reviewed by Dean Jackson.

Source/WebCore:

- Dots should not be clipped.
- Dots should be horizontally centered.
- Dots should be drawn behind the text.
- Distance from the baseline to the top of the dot should be 11.035% of font size.
- Dot diameter should be 13.247% of the font size.
- Distance between the dots (right side of the left dot to left side of the right dot) should be 9.457% of the font size.
- The "font size" used in these calculations should be clamped so it's 10px <= font size <= 40px.

Tests: editing/spelling/spelling-dots-position-2.html
       editing/spelling/spelling-dots-position-3.html
       editing/spelling/spelling-dots-position.html
       editing/spelling/spelling-dots-repaint.html

* platform/graphics/cocoa/GraphicsContextCocoa.mm:
(WebCore::colorForMarkerLineStyle): Align iOS and macOS implementations.
(WebCore::GraphicsContext::drawDotsForDocumentMarker): Place the dots correctly.
* rendering/InlineFlowBox.cpp:
(WebCore::InlineFlowBox::addToLine): The KnownToHaveNoOverflow flag should be cleared if the element has spelling dots,
    because there is no guarantee the spelling dots will lie inside the layout rect of the element.
(WebCore::InlineFlowBox::addTextBoxVisualOverflow): Update the repaint rects to include splling dot positions.
* rendering/InlineFlowBox.h: Comments should explain why, not say what.
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::paint): Draw the dots behind the text.
(WebCore::InlineTextBox::hasMarkers const): Convenience.
(WebCore::InlineTextBox::paintPlatformDocumentMarkers): Refactor bounds information into a helper function.
(WebCore::InlineTextBox::calculateUnionOfAllDocumentMarkerBounds const): Use for repaint rect calculation.
(WebCore::InlineTextBox::calculateDocumentMarkerBounds const): Place the dots correctly.
(WebCore::InlineTextBox::paintPlatformDocumentMarker): Call the helper method.
(WebCore::InlineTextBox::collectMarkedTextsForDocumentMarkers const):
(WebCore::InlineTextBox::collectMarkedTextsForDocumentMarkers): Deleted.
* rendering/InlineTextBox.h: Declare the helper methods.
* rendering/SimpleLineLayout.cpp: Simple line layout doesn't know how to paint spelling dots, so make the presence of
    spelling dots opt us out of SLL.
(WebCore::SimpleLineLayout::canUseForWithReason):
* rendering/SimpleLineLayoutCoverage.cpp:
(WebCore::SimpleLineLayout::printReason):
* rendering/SimpleLineLayoutCoverage.h: Add a new opt-out reason.

Tools:

Previously, it was impossible for WebKitTestRunner to draw spelling dots. This patch adds support for a header
at the top of test files, of the form <!-- webkit-test-runner [ spellCheckingDots=true ] --> which will cause
dots to be drawn.

* WebKitTestRunner/TestController.cpp:
(WTR::TestController::resetStateToConsistentValues):
(WTR::updateTestOptionsFromTestHeader):
(WTR::TestController::platformResetStateToConsistentValues):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestOptions.h:
(WTR::TestOptions::hasSameInitializationOptions const):
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::cocoaResetStateToConsistentValues):
* WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
* WebKitTestRunner/ios/TestControllerIOS.mm:
(WTR::TestController::platformResetStateToConsistentValues):
* WebKitTestRunner/mac/TestControllerMac.mm:
(WTR::TestController::platformResetStateToConsistentValues):

LayoutTests:

* editing/spelling/resources/VerySmallDescentAhem.ttf: Added. In order to test repaint rects,
      this is a version of Ahem with a very small descent, so that the dots don't intersect
      with the text itself.
* editing/spelling/spelling-dots-position-2-expected-mismatch.html: Added.
* editing/spelling/spelling-dots-position-2.html: Added. Make sure dots are painted in the
      correct vertical place.
* editing/spelling/spelling-dots-position-3-expected-mismatch.html: Added.
* editing/spelling/spelling-dots-position-3.html: Added. Make sure dots are painted in the
      correct vertical place.
* editing/spelling/spelling-dots-position-expected.html: Added.
* editing/spelling/spelling-dots-position.html: Added. Make sure dots are not painted in
      the wrong place.
* editing/spelling/spelling-dots-repaint-expected.html: Added.
* editing/spelling/spelling-dots-repaint.html: Added. Test repaint by drawing an element
      with spelling dots, and then deleting the element from the document. The spelling
      dots should be removed too.
* fast/writing-mode/english-bt-text-with-spelling-marker-expected.html:
* fast/writing-mode/english-bt-text-with-spelling-marker.html: Update the test to compensate
      for new spelling dot positions.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (237892 => 237893)


--- trunk/LayoutTests/ChangeLog	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/LayoutTests/ChangeLog	2018-11-06 23:06:37 UTC (rev 237893)
@@ -1,3 +1,30 @@
+2018-11-06  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        Spelling dots are drawn in the wrong place
+        https://bugs.webkit.org/show_bug.cgi?id=190764
+
+        Reviewed by Dean Jackson.
+
+        * editing/spelling/resources/VerySmallDescentAhem.ttf: Added. In order to test repaint rects,
+              this is a version of Ahem with a very small descent, so that the dots don't intersect
+              with the text itself.
+        * editing/spelling/spelling-dots-position-2-expected-mismatch.html: Added.
+        * editing/spelling/spelling-dots-position-2.html: Added. Make sure dots are painted in the
+              correct vertical place.
+        * editing/spelling/spelling-dots-position-3-expected-mismatch.html: Added.
+        * editing/spelling/spelling-dots-position-3.html: Added. Make sure dots are painted in the
+              correct vertical place.
+        * editing/spelling/spelling-dots-position-expected.html: Added.
+        * editing/spelling/spelling-dots-position.html: Added. Make sure dots are not painted in
+              the wrong place.
+        * editing/spelling/spelling-dots-repaint-expected.html: Added.
+        * editing/spelling/spelling-dots-repaint.html: Added. Test repaint by drawing an element
+              with spelling dots, and then deleting the element from the document. The spelling
+              dots should be removed too.
+        * fast/writing-mode/english-bt-text-with-spelling-marker-expected.html:
+        * fast/writing-mode/english-bt-text-with-spelling-marker.html: Update the test to compensate
+              for new spelling dot positions.
+
 2018-11-06  Ross Kirsling  <ross.kirsl...@sony.com>
 
         [WinCairo] Unreviewed layout test gardening.

Added: trunk/LayoutTests/editing/spelling/resources/VerySmallDescentAhem.ttf (0 => 237893)


--- trunk/LayoutTests/editing/spelling/resources/VerySmallDescentAhem.ttf	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/resources/VerySmallDescentAhem.ttf	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,44 @@
+\x800OS/2r\xA0\xF9E\xBC`cmap9\x96U\xEEgasp	(glyf\xF4r\xEB\x8D8\xAAhead\xDBP͵ \xE46hhea
+\xFD!$hmtx+!@Xloca\xBF6\xB8\x99%\x98.maxp	'\xC8 name\xB8)\xC6'\xE8)\xA2postc\xA1[#Q\x8C\xD6\x90\xBC\x8A\x8F\xBC\x8A\xC52\x80\xAF HW3C @ \xFE\xFF \xFF\xFE \xFF\xFC\xFF\xFF   \xF8::&~\xA0\xA1\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCF\xD0\xD1\xD2\xD4\xD5\xD6\xD7\xD8\xD9\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEB\xEC\xED\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFC\xFD\xFE\xFF1Sx\x92\xC6\xC7\xC9\xDA\xDB\xDC\xDD\x94\xA5\xA7\xA9\
 xBC\xC0   +      " & 0 : D!"!&"""""""""+"H"`"e"\xF2%\xCA00NNN	N]N\x8CN\x9
 4QkQmSAV\xD7V\xDBWg(j*l4pk~\xB5\x91\xD1\xF0\xFE\xFF\xFF\xFF (\xA0\xA1\xA2\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xD0\xD1\xD2\xD3\xD5\xD6\xD7\xD8\xD9\xDA\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEC\xED\xEE\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFD\xFE\xFF1Rx\x92\xC6\xC7\xC9\xD8\xDB\xDC\xDD\x94\xA5\xA7\xA9\xBC\xC0  	         & 0 9 D!"!&"""""""""+"H"`"d"\xF2%\xCA00NNN	N]N\x8CN\x94QkQmSAV\xD7V\xDBWg(j*l4pk~\xB5\x91\xD1\xF0\xFE\xFF\xFF\xFF\xFF\xE3\xFF\xE2\xFF\xF9\xFF\xF4\xFF\xE0\xFF\xFD\xFF\xE9\xFF\xDD\xFF\xE2\xFF\xDF\xFF\xE6\xFF\xEC\xFF\xEA
 \xFF\xD9\xFF\xD1\xFF\xDC\xFF\xD5\xFF\xDA\xFF\xCF\xFF\xEB+\xFF\xD7\xFF\xDD+\xFF
 \xD5\xFF\xDA\xFF\xE4\xFF\xE1\xFF\xD8\xFF\x9D\xFF\xC5\xFF\x9C\xFF\xDF\xFF\x9B\xFF\xDA\xFF\xDB\xFF\xDF\xFF\xDB\xFF\xEE\xFF\x94\xFF\xDC\xFF\xD9\xFF\xC7\xFF\x90\xFF\xEE\xFF\xB4\xFF\xD8\xFF\xD5\xFF\x8B\xFF\xE3\xFF\xE4\xFF\xA7\xFF\x89\xFF\x87\xFF\x88\xFF\x89\xFF\x87\xFF\x88\xFF\xAC\xFF\x87\xFF\x88\xFF\x86\xFF\x87\xFF\x88\xFF\x86\xFF\x87\xFF\xCF\xFF\x86\xFF\x87\xFF\x85\xFF\x86\xFF\x87\xFF\x85\xFF\xA8\xFF\x9B\xFF\x85\xFF\x83\xFF\x84\xFF\xC4\xFF\xC5\xFF\xA1\xFF\x81\xFF|\xFFX\xFF?\xFD\xED\xFD\xF5\xFD\xEC\xFD\xDE\xFD\xE0\xFD\xD8\xFD\xDD\xFD>\xFDo\xFDk\xFD*\xFC\xD3\xFD\xE0\xF4\xE0\xF2\xE0\xF3\xDF\xFF\xE0\xC2\xE0\x85\xE0\xBD\xE0\xBC\xE0\xBB\xE0\xB8\xE0\xAF\xE0\xA7\xE0\x9E\xDF\xC1߭\xDE\xE2\xDE\xCC\xDE\xD6\xDE\xD5޲މ\xDE\xCD\xDE\xCA޾ޥފއ\xDD\xFB\xDB$\xD0\xFE\xD1\xB3\xB3\xB2\xFA\xB2\xAC\xB2v\xB2q\xAF\x9D\xAF\x99\xADɪ5\xAA)\xA9\xF2\x99\xE7\x96\xE9\x94ڐ\xA2\x82`o?\xEF\xF6
 
 \xFF\xFF}k 3!%!!}\xEE\xFD\x8F\xF4\xFE \xFC\xE0}&\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0
 \xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8
  !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8
 \xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE
 8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0
 \xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\
 xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\x
 E8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE
 8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\x
 E8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\
 xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE
 0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xF
 C\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0
 \xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\
 xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!
 \xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!
 \xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\
 xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \
 xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0
 \xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0
 \xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !!\xE8\xFC \xFC\xE0\xE8 !
 !\xE8\xFC \xFC\xE0\x90\xE8X!!\xE8\xFCX\xC8\x90\xE8X!!\xE8\xFCX\xC8\xC8\xFF8\x90 3#\xC8\xC8\xC8 \xFC\xC8\xFF8
 \x90 3#\xC8\xC8\xC8 \xFC\x80M\xBA\xDAL_<\xF5	\xE8\xB3o_Y\xC4ݫ$\xFF8\xE8  \xFF\xFE\xE8\xE8\xE8}\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8
 \xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE
 8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\
 xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xF4\xE8M\xFA\xA7\xC8d\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE
 8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xC8\xE8\xC8!.;HUbo|\x89\x96\xA3\xB0\xBD\xCA\xD7\xE4\xF1\xFE%2?LYfs\x80\x8D\x9A\xA7\xB4\xC1\xCE\xDB\xE8\xF5)6CP]jw\x84\x91\x9E\xAB\xB8\xC5\xD2\xDF\xEC\xF9 -:GTan{\x88\x95\xA2\xAF\xBC\xC9\xD6\xE3\xF0\xFD
+$1>KXer\x8C\x99\xA6\xB3\xC0\xCD\xDA\xE7\xF4(5BO\iv\x83\x90\x9D\xAA\xB7\xC4\xD1\xDE\xEB\xF8,9FS`mz\x87\x94\xA1\xAE\xBB\xC8\xD5\xE2\xEF\xFC	#0=JWdq~\x8B\x98\xA5\xA5\xB2\xBF\xCC\xD9\xE6\xF3+'4AN[hu\x82\x8F\x9C\xA9\xB6\xC3\xD0\xDD\xEA\xF7				+	8	E	R	_	l	y	\x86	\x93	\xA0	\xAD	\xBA	\xC7	\xD4	\xE1	\xEE	\xFB
+
+
+"
+/
+<
+I
+V
+c
+p
+}
+\x8A
+\x97
+\xA4
+\xB1
+\xBE
+\xCB
+\xD8
+\xE5
+\xF2
+\xFF&3@MZgt\x81\x8E\x9B\xA8\xB5\xC2\xCF\xDC\xE9\xF6*7DDDDDDDDDDDDDQ^kx\x85\x92\x9F\xAC\xB9\xC6\xD3\xE0\xED\xFA+++!+.+;+H+U$\xB6\xF0\xF0\xF8"(0H
+hP$\xB8R\xDC\xF8.&*1BFR
+VV)h\x91\x95\x9C	\xF0\xA0	\x90	\x98	"\xA6	\xC8	\xD0	\xE8	
+h\xF0	$'X	R'|	'\xCE	'\xD6	'\xE4The Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50AhemThe 
 Ahem font was developed by Todd Fahrner and Myles C. Maxfield to help test writers develop predictable tests. The units per em is 1000, the advance is 800, and 
 the descent is 200, thereby making the em square exactly square. The glyphs for most characters is simply a box which fills this square. The codepoints mapped to this full square with a full advance are the following ranges: U+20-U+26, U+28-U+6F, U+71-U+7E, U+A0-U+C8, U+CA-U+FF, U+131, U+152-U+153, U+178, U+192, U+2C6-U+2C7, U+2C9,
  U+2D8-U+2DD, U+394, U+3A5, U+3A7, U+3A9, U+3BC, U+3C0, U+2013-U+2014, U+2018-U+201A, U+201C-U+201E, U+2020-U+2022, U+2026, U+2030, U+2039-U+203A, U+2044, U+2122, U+2
 126, U+2202, U+2206, U+220F, U+2211-U+2212, U+2219-U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-U+2265, U+22F2, U+25CA, U+3007, U+4E00, U+4E03, U+4E09, U+4E5D, U+4E8C, U+4E94, U+516B, U+516D, U+5341, U+56D7, U+56DB, U+571F, U+6728, U+6C34, U+706B, U+91D1, U+F000-U+F002. The codepoints which are mapped to something else are the f
 ollowing: " " (U+20): No path but full advance; "p" (U+70): Path has 0 ascent but full descent; "\xC9" (U+C9): Path has 0 descent but full ascent; Non-br
 eaking space (U+A0): No path but full advance; Zero-width non-breaking space (U+FEFF): No path and 0 advance; En space (U+2002): No path and half advance; Em space (U+2003): No path but full advance; Three-per-em space (U+2004): No path and one third advance; Four-per-em space (U+2005): No path and one quarter advance; Six-per-em 
 space (U+2006): No path and one sixth advance; Thin space (U+2009): No path and one fifth advance; Hair space (U+200A): No path and one tenth advance; Zero width spac
 e (U+200B): No path and no advance; Ideographic space (U+3000): No path but full advance; Zero width non-joiner (U+200C): No path and no advance; Zero width joiner (U+200D): No path and no advance; Greek capital letter Chi (U+3A7): Thin horizontal stripe and full advance; "j*" (U+6A2A): Thin horizontal stripe and full advance; Gr
 eek capital letter Upsilon (U+3A5): Thin vertical stripe and full advance; "~\xB5" (U+7EB5): Thin vertical stripe and full advance.http://www.w3c.orghttp://dev.w
 3.org/CSS/fonts/ahem/COPYING
+The Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50Ahemhttp://www.w3c.orghttp://dev.w3.org/CSS/fonts/ahem/COPYING
+AhemRegularAhemThe Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50AhemThe Ahem font was developed by 
 Todd Fahrner and Myles C. Maxfield to help test writers develop predictable tests. The units per em is 1000, the advance is 800, and the descent is 200, thereby mak
 ing the em square exactly square. The glyphs for most characters is simply a box which fills this square. The codepoints mapped to this full square with a full advance are the following ranges: U+20-U+26, U+28-U+6F, U+71-U+7E, U+A0-U+C8, U+CA-U+FF, U+131, U+152-U+153, U+178, U+192, U+2C6-U+2C7, U+2C9, U+2D8-U+2DD, U+394, U+3A5, U+
 3A7, U+3A9, U+3BC, U+3C0, U+2013-U+2014, U+2018-U+201A, U+201C-U+201E, U+2020-U+2022, U+2026, U+2030, U+2039-U+203A, U+2044, U+2122, U+2126, U+2202, U+2206, U+220F, U
 +2211-U+2212, U+2219-U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-U+2265, U+22F2, U+25CA, U+3007, U+4E00, U+4E03, U+4E09, U+4E5D, U+4E8C, U+4E94, U+516B, U+516D, U+5341, U+56D7, U+56DB, U+571F, U+6728, U+6C34, U+706B, U+91D1, U+F000-U+F002. The codepoints which are mapped to something else are the following: " " (U+20): No pa
 th but full advance; "p" (U+70): Path has 0 ascent but full descent; "\xC9" (U+C9): Path has 0 descent but full ascent; Non-breaking space (U+A0): No path b
 ut full advance; Zero-width non-breaking space (U+FEFF): No path and 0 advance; En space (U+2002): No path and half advance; Em space (U+2003): No path but full advance; Three-per-em space (U+2004): No path and one third advance; Four-per-em space (U+2005): No path and one quarter advance; Six-per-em space (U+2006): No path and one
  sixth advance; Thin space (U+2009): No path and one fifth advance; Hair space (U+200A): No path and one tenth advance; Zero width space (U+200B): No path and no adva
 nce; Ideographic space (U+3000): No path but full advance; Zero width non-joiner (U+200C): No path and no advance; Zero width joiner (U+200D): No path and no advance; Greek capital letter Chi (U+3A7): Thin horizontal stripe and full advance; "j*" (U+6A2A): Thin horizontal stripe and full advance; Greek capital letter Upsilon (U+
 3A5): Thin vertical stripe and full advance; "~\xB5" (U+7EB5): Thin vertical stripe and full advance.http://www.w3c.orghttp://dev.w3.org/CSS/fonts/ahem/COPYING
+AhemRegularAhem\xFF{	+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81\x83\x84\x85\x86\x88\x89\x8A\x8B\x8D\x8E\x90\x91\x93\x96\x97\x9D\x9E\xA0\xA1\xA2\xA3\xA4\xA9\xAA\xAC\xAD\xAE\xAF\xB6\xB7\xB8\xBA\xBD\xC3\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xB0\xB1\xBB\x
 A6\xA8\x9F\x9B\xB2\xB3\xC4\xB4\xB5\xC5\x82\xC2\x87\xAB\xC6\xBE\xBF\xBC\x8C\x98\x9A\x99\xA5\x92\x9C\x8F\x94\x95\xA7\xB9\xD2\xC0\xC1	
++ !"#$%&'(NULLglyph243glyph204glyph205HTDELuniFEFFuni2002uni2003uni2004uni2005uni2006uni2009uni200Auni200Buni3000	afii61664afii301uni4E00uni4E8Cuni4E09uni56DBuni4E94uni516Duni4E03uni516Buni4E5Duni5341uni3007uni56D7uni706Buni6C34uni6728uni91D1uni571Funi03A7uni6A2Auni03A5uni7EB5
\ No newline at end of file

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position-2-expected-mismatch.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position-2-expected-mismatch.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position-2-expected-mismatch.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position-2.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position-2.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position-2.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,67 @@
+<!DOCTYPE html><!-- webkit-test-runner [ spellCheckingDots=true ] -->
+<html>
+<head>
+
+<style>
+.editing {
+    font-family: 'Times New Roman';
+    font-size: 36px;
+    color: transparent;
+}
+</style>
+<script src="" language="_javascript_" type="text/_javascript_" ></script>
+
+<script>
+function editingTest() {
+    typeCharacterCommand('w');
+    typeCharacterCommand('a');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('e');
+    typeCharacterCommand('r');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('d');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('a');
+    typeCharacterCommand(' ');
+    let ascentSetter = document.createElement("div");
+    ascentSetter.style.width = "1px";
+    ascentSetter.style.height = "150px";
+    ascentSetter.style.display = "inline-block";
+    let root = document.getElementById("root");
+    root.appendChild(ascentSetter);
+    let baseline = ascentSetter.offsetTop + ascentSetter.offsetHeight;
+    let left = root.offsetLeft;
+    let width = ascentSetter.offsetLeft - left;
+    let fontSize = Number.parseInt(window.getComputedStyle(root).getPropertyValue("font-size"));
+    let blocker = document.createElement("div");
+    blocker.style.background = ""
+    blocker.style.position = "absolute";
+    blocker.style.left = `${left}px`;
+    blocker.style.top = `${baseline + 1 + fontSize * 0.11035}px`;
+    blocker.style.width = `${width}px`;
+    blocker.style.height = `${fontSize * 0.13247}px`;
+    document.body.appendChild(blocker);
+    root.blur();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+<div contenteditable id="root" class="editing">
+<span id="test"></span>
+</div>
+
+<script>
+    if (window.internals)
+        internals.setContinuousSpellCheckingEnabled(true);
+    runEditingTest();
+</script>
+
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position-3-expected-mismatch.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position-3-expected-mismatch.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position-3-expected-mismatch.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position-3.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position-3.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position-3.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,67 @@
+<!DOCTYPE html><!-- webkit-test-runner [ spellCheckingDots=true ] -->
+<html>
+<head>
+
+<style>
+.editing {
+    font-family: 'Times New Roman';
+    font-size: 36px;
+    color: transparent;
+}
+</style>
+<script src="" language="_javascript_" type="text/_javascript_" ></script>
+
+<script>
+function editingTest() {
+    typeCharacterCommand('w');
+    typeCharacterCommand('a');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('e');
+    typeCharacterCommand('r');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('d');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('a');
+    typeCharacterCommand(' ');
+    let ascentSetter = document.createElement("div");
+    ascentSetter.style.width = "1px";
+    ascentSetter.style.height = "150px";
+    ascentSetter.style.display = "inline-block";
+    let root = document.getElementById("root");
+    root.appendChild(ascentSetter);
+    let baseline = ascentSetter.offsetTop + ascentSetter.offsetHeight;
+    let left = root.offsetLeft;
+    let width = ascentSetter.offsetLeft - left;
+    let fontSize = Number.parseInt(window.getComputedStyle(root).getPropertyValue("font-size"));
+    let blocker = document.createElement("div");
+    blocker.style.background = ""
+    blocker.style.position = "absolute";
+    blocker.style.left = `${left}px`;
+    blocker.style.top = `${baseline - 1 + fontSize * 0.11035}px`;
+    blocker.style.width = `${width}px`;
+    blocker.style.height = `${fontSize * 0.13247}px`;
+    document.body.appendChild(blocker);
+    root.blur();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+<div contenteditable id="root" class="editing">
+<span id="test"></span>
+</div>
+
+<script>
+    if (window.internals)
+        internals.setContinuousSpellCheckingEnabled(true);
+    runEditingTest();
+</script>
+
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position-expected.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position-expected.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.editing {
+    font-family: 'Times New Roman';
+    font-size: 36px;
+}
+</style>
+</head>
+<body>
+<div>There should be no misspelling dots visible below (because they're covered up by a div)</div>
+<div contenteditable="" id="root" class="editing">wafewerewdfea&nbsp;<span id="test"></span><div style="background-color: black; width: 1px; height: 150px; display: inline-block; background-position: initial initial; background-repeat: initial initial;"></div></div>
+<script>
+    runEditingTest();
+</script><div style="background-color: black; position: absolute; left: 8px; top: 179.9726px; width: 237px; height: 4.7689200000000005px; background-position: initial initial; background-repeat: initial initial;"></div>
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-position.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-position.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-position.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,68 @@
+<!DOCTYPE html><!-- webkit-test-runner [ spellCheckingDots=true ] -->
+<html>
+<head>
+
+<style>
+.editing {
+    font-family: 'Times New Roman';
+    font-size: 36px;
+}
+</style>
+<script src="" language="_javascript_" type="text/_javascript_" ></script>
+
+<script>
+function editingTest() {
+    typeCharacterCommand('w');
+    typeCharacterCommand('a');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('e');
+    typeCharacterCommand('r');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('d');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('a');
+    typeCharacterCommand(' ');
+    let ascentSetter = document.createElement("div");
+    ascentSetter.style.background = ""
+    ascentSetter.style.width = "1px";
+    ascentSetter.style.height = "150px";
+    ascentSetter.style.display = "inline-block";
+    let root = document.getElementById("root");
+    root.appendChild(ascentSetter);
+    let baseline = ascentSetter.offsetTop + ascentSetter.offsetHeight;
+    let left = root.offsetLeft;
+    let width = ascentSetter.offsetLeft - left;
+    let fontSize = Number.parseInt(window.getComputedStyle(root).getPropertyValue("font-size"));
+    let blocker = document.createElement("div");
+    blocker.style.background = ""
+    blocker.style.position = "absolute";
+    blocker.style.left = `${left}px`;
+    blocker.style.top = `${baseline + fontSize * 0.11035}px`;
+    blocker.style.width = `${width}px`;
+    blocker.style.height = `${fontSize * 0.13247}px`;
+    document.body.appendChild(blocker);
+    root.blur();
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+<div>There should be no misspelling dots visible below (because they're covered up by a div)</div>
+<div contenteditable id="root" class="editing">
+<span id="test"></span>
+</div>
+
+<script>
+    if (window.internals)
+        internals.setContinuousSpellCheckingEnabled(true);
+    runEditingTest();
+</script>
+
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-repaint-expected.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-repaint-expected.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-repaint-expected.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Editing Test</title>
+</head>
+<body>
+This test passes if you don't see any dots below.
+</body>
+</html>

Added: trunk/LayoutTests/editing/spelling/spelling-dots-repaint.html (0 => 237893)


--- trunk/LayoutTests/editing/spelling/spelling-dots-repaint.html	                        (rev 0)
+++ trunk/LayoutTests/editing/spelling/spelling-dots-repaint.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -0,0 +1,59 @@
+<!DOCTYPE html><!-- webkit-test-runner [ spellCheckingDots=true ] -->
+<html>
+<head>
+
+<style>
+@font-face {
+    font-family: "WebFont";
+    src: url("resources/VerySmallDescentAhem.ttf") format("truetype");
+}
+.editing {
+    font: 36px "WebFont";
+}
+</style>
+<script src="" language="_javascript_" type="text/_javascript_" ></script>
+
+<script>
+function editingTest() {
+    typeCharacterCommand('w');
+    typeCharacterCommand('a');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('e');
+    typeCharacterCommand('r');
+    typeCharacterCommand('e');
+    typeCharacterCommand('w');
+    typeCharacterCommand('d');
+    typeCharacterCommand('f');
+    typeCharacterCommand('e');
+    typeCharacterCommand('a');
+    typeCharacterCommand(' ');
+    window.setTimeout(function() {
+        let root = document.getElementById("root");
+        root.parentElement.removeChild(root);
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }, 20);
+}
+
+</script>
+
+<title>Editing Test</title>
+</head>
+<body>
+This test passes if you don't see any dots below.
+<div contenteditable id="root" class="editing">
+<span id="test"></span>
+</div>
+
+<script>
+    if (window.internals)
+        internals.setContinuousSpellCheckingEnabled(true);
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+    runEditingTest();
+</script>
+
+</body>
+</html>

Modified: trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker-expected.html (237892 => 237893)


--- trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker-expected.html	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker-expected.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -15,6 +15,7 @@
     left: 0;
     width: 200px;
     font: 20px/1 Ahem;
+    line-height: 1.2;
 }
 </style>
 </head>

Modified: trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker.html (237892 => 237893)


--- trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker.html	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/LayoutTests/fast/writing-mode/english-bt-text-with-spelling-marker.html	2018-11-06 23:06:37 UTC (rev 237893)
@@ -11,6 +11,7 @@
 body {
     -webkit-writing-mode: horizontal-bt;
     font: 20px/1 Ahem;
+    line-height: 1.2;
 }
 
 #test {

Modified: trunk/LayoutTests/platform/ios/TestExpectations (237892 => 237893)


--- trunk/LayoutTests/platform/ios/TestExpectations	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2018-11-06 23:06:37 UTC (rev 237893)
@@ -3212,3 +3212,9 @@
 http/tests/xmlhttprequest/gzip-content-type-no-content-encoding.html [ Pass ]
 
 webkit.org/b/173041 http/tests/websocket/tests/hybi/handshake-ok-with-legacy-sec-websocket-response-headers.html [ Pass Failure ]
+
+# WK2 spelling dot test infrastructure isn't hooked up on iOS
+webkit.org/b/190764 editing/spelling/spelling-dots-repaint.html [ Skip ]
+webkit.org/b/190764 editing/spelling/spelling-dots-position.html [ Skip ]
+webkit.org/b/190764 editing/spelling/spelling-dots-position-2.html [ Skip ]
+webkit.org/b/190764 editing/spelling/spelling-dots-position-3.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (237892 => 237893)


--- trunk/Source/WebCore/ChangeLog	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/ChangeLog	2018-11-06 23:06:37 UTC (rev 237893)
@@ -1,3 +1,48 @@
+2018-11-06  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        Spelling dots are drawn in the wrong place
+        https://bugs.webkit.org/show_bug.cgi?id=190764
+
+        Reviewed by Dean Jackson.
+
+        - Dots should not be clipped.
+        - Dots should be horizontally centered.
+        - Dots should be drawn behind the text.
+        - Distance from the baseline to the top of the dot should be 11.035% of font size.
+        - Dot diameter should be 13.247% of the font size.
+        - Distance between the dots (right side of the left dot to left side of the right dot) should be 9.457% of the font size.
+        - The "font size" used in these calculations should be clamped so it's 10px <= font size <= 40px.
+
+        Tests: editing/spelling/spelling-dots-position-2.html
+               editing/spelling/spelling-dots-position-3.html
+               editing/spelling/spelling-dots-position.html
+               editing/spelling/spelling-dots-repaint.html
+
+        * platform/graphics/cocoa/GraphicsContextCocoa.mm:
+        (WebCore::colorForMarkerLineStyle): Align iOS and macOS implementations.
+        (WebCore::GraphicsContext::drawDotsForDocumentMarker): Place the dots correctly.
+        * rendering/InlineFlowBox.cpp:
+        (WebCore::InlineFlowBox::addToLine): The KnownToHaveNoOverflow flag should be cleared if the element has spelling dots,
+            because there is no guarantee the spelling dots will lie inside the layout rect of the element.
+        (WebCore::InlineFlowBox::addTextBoxVisualOverflow): Update the repaint rects to include splling dot positions.
+        * rendering/InlineFlowBox.h: Comments should explain why, not say what.
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::paint): Draw the dots behind the text.
+        (WebCore::InlineTextBox::hasMarkers const): Convenience.
+        (WebCore::InlineTextBox::paintPlatformDocumentMarkers): Refactor bounds information into a helper function.
+        (WebCore::InlineTextBox::calculateUnionOfAllDocumentMarkerBounds const): Use for repaint rect calculation.
+        (WebCore::InlineTextBox::calculateDocumentMarkerBounds const): Place the dots correctly.
+        (WebCore::InlineTextBox::paintPlatformDocumentMarker): Call the helper method.
+        (WebCore::InlineTextBox::collectMarkedTextsForDocumentMarkers const):
+        (WebCore::InlineTextBox::collectMarkedTextsForDocumentMarkers): Deleted.
+        * rendering/InlineTextBox.h: Declare the helper methods.
+        * rendering/SimpleLineLayout.cpp: Simple line layout doesn't know how to paint spelling dots, so make the presence of
+            spelling dots opt us out of SLL.
+        (WebCore::SimpleLineLayout::canUseForWithReason):
+        * rendering/SimpleLineLayoutCoverage.cpp:
+        (WebCore::SimpleLineLayout::printReason):
+        * rendering/SimpleLineLayoutCoverage.h: Add a new opt-out reason.
+
 2018-11-06  Per Arne Vollan  <pvol...@apple.com>
 
         REGRESSION (r230523): Caps lock indicator not shown in password field

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextCocoa.mm (237892 => 237893)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextCocoa.mm	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextCocoa.mm	2018-11-06 23:06:37 UTC (rev 237893)
@@ -185,7 +185,6 @@
 
 static CGColorRef colorForMarkerLineStyle(DocumentMarkerLineStyle::Mode style, bool useDarkMode)
 {
-#if PLATFORM(MAC)
     switch (style) {
     // Red
     case DocumentMarkerLineStyle::Mode::Spelling:
@@ -199,19 +198,6 @@
     case DocumentMarkerLineStyle::Mode::Grammar:
         return cachedCGColor(useDarkMode ? Color { 50, 215, 75, 217 } : Color { 25, 175, 50, 191 });
     }
-#else
-    UNUSED_PARAM(useDarkMode);
-    switch (style) {
-    case DocumentMarkerLineStyle::Mode::Spelling:
-        return [getUIColorClass() systemRedColor].CGColor;
-    case DocumentMarkerLineStyle::Mode::DictationAlternatives:
-    case DocumentMarkerLineStyle::Mode::TextCheckingDictationPhraseWithAlternatives:
-    case DocumentMarkerLineStyle::Mode::AutocorrectionReplacement:
-        return [getUIColorClass() systemBlueColor].CGColor;
-    case DocumentMarkerLineStyle::Mode::Grammar:
-        return [getUIColorClass() systemGreenColor].CGColor;
-    }
-#endif
 }
 
 void GraphicsContext::drawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle style)
@@ -219,28 +205,33 @@
     if (paintingDisabled())
         return;
 
-    auto circleColor = colorForMarkerLineStyle(style.mode, style.shouldUseDarkAppearance);
+    // We want to find the number of full dots, so we're solving the equations:
+    // dotDiameter = height
+    // dotDiameter / dotGap = 13.247 / 9.457
+    // numberOfGaps = numberOfDots - 1
+    // dotDiameter * numberOfDots + dotGap * numberOfGaps = width
 
-    auto lineThickness = rect.height();
-    auto patternGapWidth = lineThickness / 3;
-    auto patternWidth = lineThickness + patternGapWidth;
-
-    FloatPoint offsetPoint = rect.location();
     auto width = rect.width();
-    float widthMod = fmodf(width, patternWidth);
-    if (patternWidth - widthMod > patternGapWidth) {
-        float gapIncludeWidth = 0;
-        if (width > patternWidth)
-            gapIncludeWidth = patternGapWidth;
-        offsetPoint.move(floor((widthMod + gapIncludeWidth) / 2), 0);
-        width -= widthMod;
-    }
+    auto dotDiameter = rect.height();
+    auto dotGap = dotDiameter * 9.457 / 13.247;
+    auto numberOfDots = (width + dotGap) / (dotDiameter + dotGap);
+    auto numberOfWholeDots = static_cast<unsigned>(numberOfDots);
+    auto numberOfWholeGaps = numberOfWholeDots - 1;
 
+    // Center the dots
+    auto offset = (width - (dotDiameter * numberOfWholeDots + dotGap * numberOfWholeGaps)) / 2;
+
+    auto circleColor = colorForMarkerLineStyle(style.mode, style.shouldUseDarkAppearance);
+
     CGContextRef platformContext = this->platformContext();
     CGContextStateSaver stateSaver { platformContext };
     CGContextSetFillColorWithColor(platformContext, circleColor);
-    for (int x = 0; x < width; x += patternWidth)
-        CGContextAddEllipseInRect(platformContext, CGRectMake(offsetPoint.x() + x, offsetPoint.y(), lineThickness, lineThickness));
+    for (unsigned i = 0; i < numberOfWholeDots; ++i) {
+        auto location = rect.location();
+        location.move(offset + i * (dotDiameter + dotGap), 0);
+        auto size = FloatSize(dotDiameter, dotDiameter);
+        CGContextAddEllipseInRect(platformContext, FloatRect(location, size));
+    }
     CGContextSetCompositeOperation(platformContext, kCGCompositeSover);
     CGContextFillPath(platformContext);
 }

Modified: trunk/Source/WebCore/rendering/InlineFlowBox.cpp (237892 => 237893)


--- trunk/Source/WebCore/rendering/InlineFlowBox.cpp	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/InlineFlowBox.cpp	2018-11-06 23:06:37 UTC (rev 237893)
@@ -158,7 +158,12 @@
         const RenderStyle& childStyle = child->lineStyle();
         if (child->behavesLikeText()) {
             const RenderStyle* childStyle = &child->lineStyle();
-            if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMark::None || childStyle->hasPositiveStrokeWidth())
+            bool hasMarkers = false;
+            if (is<InlineTextBox>(child)) {
+                const auto* textBox = downcast<InlineTextBox>(child);
+                hasMarkers = textBox->hasMarkers();
+            }
+            if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMark::None || childStyle->hasPositiveStrokeWidth() || hasMarkers)
                 child->clearKnownToHaveNoOverflow();
         } else if (child->renderer().isReplaced()) {
             const RenderBox& box = downcast<RenderBox>(child->renderer());
@@ -928,6 +933,10 @@
     
     logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
                                        logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
+
+    auto documentMarkerBounds = textBox.calculateUnionOfAllDocumentMarkerBounds();
+    documentMarkerBounds.move(textBox.logicalLeft(), textBox.logicalTop());
+    logicalVisualOverflow = unionRect(logicalVisualOverflow, LayoutRect(documentMarkerBounds));
                                     
     textBox.setLogicalOverflowRect(logicalVisualOverflow);
 }

Modified: trunk/Source/WebCore/rendering/InlineFlowBox.h (237892 => 237893)


--- trunk/Source/WebCore/rendering/InlineFlowBox.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/InlineFlowBox.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -292,8 +292,7 @@
     }
 
     void computeReplacedAndTextLineTopAndBottom(LayoutUnit& lineTop, LayoutUnit& lineBottom) const;
-    
-    // Used to calculate the underline offset for TextUnderlinePosition::Under.
+
     void maxLogicalBottomForTextDecorationLine(float& maxLogicalBottom, const RenderElement* decorationRenderer, OptionSet<TextDecoration>) const;
     void minLogicalTopForTextDecorationLine(float& minLogicalTop, const RenderElement* decorationRenderer, OptionSet<TextDecoration>) const;
 

Modified: trunk/Source/WebCore/rendering/InlineTextBox.cpp (237892 => 237893)


--- trunk/Source/WebCore/rendering/InlineTextBox.cpp	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/InlineTextBox.cpp	2018-11-06 23:06:37 UTC (rev 237893)
@@ -543,6 +543,9 @@
     if (paintInfo.phase == PaintPhase::Foreground)
         renderer().page().addRelevantRepaintedObject(&renderer(), IntRect(boxOrigin.x(), boxOrigin.y(), logicalWidth(), logicalHeight()));
 
+    if (paintInfo.phase == PaintPhase::Foreground)
+        paintPlatformDocumentMarkers(context, boxOrigin);
+
     // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only).
     bool shouldPaintSelectionForeground = haveSelection && !useCustomUnderlines;
     Vector<MarkedText> markedTexts;
@@ -620,12 +623,8 @@
     }
 
     // 3. Paint fancy decorations, including composition underlines and platform-specific underlines for spelling errors, grammar errors, et cetera.
-    if (paintInfo.phase == PaintPhase::Foreground) {
-        paintPlatformDocumentMarkers(context, boxOrigin);
-
-        if (useCustomUnderlines)
-            paintCompositionUnderlines(paintInfo, boxOrigin);
-    }
+    if (paintInfo.phase == PaintPhase::Foreground && useCustomUnderlines)
+        paintCompositionUnderlines(paintInfo, boxOrigin);
     
     if (shouldRotate)
         context.concatCTM(rotation(boxRect, Counterclockwise));
@@ -665,12 +664,46 @@
     return { clampedOffset(start), clampedOffset(end) };
 }
 
+bool InlineTextBox::hasMarkers() const
+{
+    return collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration).size();
+}
+
 void InlineTextBox::paintPlatformDocumentMarkers(GraphicsContext& context, const FloatPoint& boxOrigin)
 {
+    // This must match calculateUnionOfAllDocumentMarkerBounds().
     for (auto& markedText : subdivide(collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration), OverlapStrategy::Frontmost))
         paintPlatformDocumentMarker(context, boxOrigin, markedText);
 }
 
+FloatRect InlineTextBox::calculateUnionOfAllDocumentMarkerBounds() const
+{
+    // This must match paintPlatformDocumentMarkers().
+    FloatRect result;
+    for (auto& markedText : subdivide(collectMarkedTextsForDocumentMarkers(TextPaintPhase::Decoration), OverlapStrategy::Frontmost))
+        result = unionRect(result, calculateDocumentMarkerBounds(markedText));
+    return result;
+}
+
+FloatRect InlineTextBox::calculateDocumentMarkerBounds(const MarkedText& markedText) const
+{
+    auto& font = lineFont();
+    auto ascent = font.fontMetrics().ascent();
+    auto fontSize = std::min(std::max(font.size(), 10.0f), 40.0f);
+    auto y = ascent + 0.11035 * fontSize;
+    auto height = 0.13247 * fontSize;
+
+    // Avoid measuring the text when the entire line box is selected as an optimization.
+    if (markedText.startOffset || markedText.endOffset != clampedOffset(end() + 1)) {
+        TextRun run = createTextRun();
+        LayoutRect selectionRect = LayoutRect(0, y, 0, height);
+        lineFont().adjustSelectionRectForText(run, selectionRect, markedText.startOffset, markedText.endOffset);
+        return selectionRect;
+    }
+
+    return FloatRect(0, y, logicalWidth(), height);
+}
+
 void InlineTextBox::paintPlatformDocumentMarker(GraphicsContext& context, const FloatPoint& boxOrigin, const MarkedText& markedText)
 {
     // Never print spelling/grammar markers (5327887)
@@ -680,27 +713,11 @@
     if (m_truncation == cFullTruncation)
         return;
 
-    float start = 0; // start of line to draw, relative to tx
-    float width = logicalWidth(); // how much line to draw
+    auto bounds = calculateDocumentMarkerBounds(markedText);
 
-    // Avoid measuring the text when the entire line box is selected as an optimization.
-    if (markedText.startOffset || markedText.endOffset != clampedOffset(end() + 1)) {
-        // Calculate start & width
-        int deltaY = renderer().style().isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
-        int selHeight = selectionHeight();
-        FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
-        TextRun run = createTextRun();
-
-        LayoutRect selectionRect = LayoutRect(startPoint, FloatSize(0, selHeight));
-        lineFont().adjustSelectionRectForText(run, selectionRect, markedText.startOffset, markedText.endOffset);
-        IntRect markerRect = enclosingIntRect(selectionRect);
-        start = markerRect.x() - startPoint.x();
-        width = markerRect.width();
-    }
-
-    auto lineStyleForMarkedTextType = [&] (MarkedText::Type type) -> DocumentMarkerLineStyle {
+    auto lineStyleForMarkedTextType = [&]() -> DocumentMarkerLineStyle {
         bool shouldUseDarkAppearance = renderer().document().useDarkAppearance();
-        switch (type) {
+        switch (markedText.type) {
         case MarkedText::SpellingError:
             return { DocumentMarkerLineStyle::Mode::Spelling, shouldUseDarkAppearance };
         case MarkedText::GrammarError:
@@ -720,25 +737,8 @@
         }
     };
 
-    // IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
-    // make sure to fit within those bounds.  This means the top pixel(s) of the underline will overlap the
-    // bottom pixel(s) of the glyphs in smaller font sizes.  The alternatives are to increase the line spacing (bad!!)
-    // or decrease the underline thickness.  The overlap is actually the most useful, and matches what AppKit does.
-    // So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
-    // we pin to two pixels under the baseline.
-    int lineThickness = 3;
-    int baseline = lineStyle().fontMetrics().ascent();
-    int descent = logicalHeight() - baseline;
-    int underlineOffset;
-    if (descent <= (2 + lineThickness)) {
-        // Place the underline at the very bottom of the text in small/medium fonts.
-        underlineOffset = logicalHeight() - lineThickness;
-    } else {
-        // In larger fonts, though, place the underline up near the baseline to prevent a big gap.
-        underlineOffset = baseline + 2;
-    }
-
-    context.drawDotsForDocumentMarker(FloatRect(boxOrigin.x() + start, boxOrigin.y() + underlineOffset, width, lineThickness), lineStyleForMarkedTextType(markedText.type));
+    bounds.moveBy(boxOrigin);
+    context.drawDotsForDocumentMarker(bounds, lineStyleForMarkedTextType());
 }
 
 auto InlineTextBox::computeStyleForUnmarkedMarkedText(const PaintInfo& paintInfo) const -> MarkedTextStyle
@@ -855,7 +855,7 @@
     return result;
 }
 
-Vector<MarkedText> InlineTextBox::collectMarkedTextsForDocumentMarkers(TextPaintPhase phase)
+Vector<MarkedText> InlineTextBox::collectMarkedTextsForDocumentMarkers(TextPaintPhase phase) const
 {
     ASSERT_ARG(phase, phase == TextPaintPhase::Background || phase == TextPaintPhase::Foreground || phase == TextPaintPhase::Decoration);
 

Modified: trunk/Source/WebCore/rendering/InlineTextBox.h (237892 => 237893)


--- trunk/Source/WebCore/rendering/InlineTextBox.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/InlineTextBox.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -157,6 +157,10 @@
     virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
     virtual float positionForOffset(unsigned offset) const;
 
+    bool hasMarkers() const;
+    FloatRect calculateUnionOfAllDocumentMarkerBounds() const;
+    FloatRect calculateDocumentMarkerBounds(const MarkedText&) const;
+
 private:
     struct MarkedTextStyle;
     struct StyledMarkedText;
@@ -164,7 +168,7 @@
     enum class TextPaintPhase { Background, Foreground, Decoration };
 
     Vector<MarkedText> collectMarkedTextsForDraggedContent();
-    Vector<MarkedText> collectMarkedTextsForDocumentMarkers(TextPaintPhase);
+    Vector<MarkedText> collectMarkedTextsForDocumentMarkers(TextPaintPhase) const;
 
     MarkedTextStyle computeStyleForUnmarkedMarkedText(const PaintInfo&) const;
     StyledMarkedText resolveStyleForMarkedText(const MarkedText&, const MarkedTextStyle& baseStyle, const PaintInfo&);

Modified: trunk/Source/WebCore/rendering/SimpleLineLayout.cpp (237892 => 237893)


--- trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/SimpleLineLayout.cpp	2018-11-06 23:06:37 UTC (rev 237893)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "SimpleLineLayout.h"
 
+#include "DocumentMarkerController.h"
 #include "FontCache.h"
 #include "Frame.h"
 #include "GraphicsContext.h"
@@ -313,6 +314,9 @@
         if (child->selectionState() != RenderObject::SelectionNone)
             SET_REASON_AND_RETURN_IF_NEEDED(FlowChildIsSelected, reasons, includeReasons);
         if (is<RenderText>(*child)) {
+            const auto& renderText = downcast<RenderText>(*child);
+            if (!renderText.document().markers().markersFor(renderText.textNode()).isEmpty())
+                SET_REASON_AND_RETURN_IF_NEEDED(FlowIncludesDocumentMarkers, reasons, includeReasons);
             child = child->nextSibling();
             continue;
         }

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.cpp (237892 => 237893)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.cpp	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.cpp	2018-11-06 23:06:37 UTC (rev 237893)
@@ -193,8 +193,11 @@
         stream << "column with vertical-align != baseline";
         break;
     case MultiColumnFlowIsFloating:
-        stream << "column with floating objecgts";
+        stream << "column with floating objects";
         break;
+    case FlowIncludesDocumentMarkers:
+        stream << "text includes document markers";
+        break;
     case FlowTextIsEmpty:
     case FlowHasNoChild:
     case FlowHasNoParent:

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.h (237892 => 237893)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutCoverage.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -90,7 +90,8 @@
     MultiColumnFlowHasColumnSpanner       = 1LLU  << 52,
     MultiColumnFlowVerticalAlign          = 1LLU  << 53,
     MultiColumnFlowIsFloating             = 1LLU  << 54,
-    EndOfReasons                          = 1LLU  << 55
+    FlowIncludesDocumentMarkers           = 1LLU  << 55,
+    EndOfReasons                          = 1LLU  << 56
 };
 const unsigned NoReason = 0;
 

Modified: trunk/Tools/ChangeLog (237892 => 237893)


--- trunk/Tools/ChangeLog	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/ChangeLog	2018-11-06 23:06:37 UTC (rev 237893)
@@ -1,3 +1,29 @@
+2018-11-06  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        Spelling dots are drawn in the wrong place
+        https://bugs.webkit.org/show_bug.cgi?id=190764
+
+        Reviewed by Dean Jackson.
+
+        Previously, it was impossible for WebKitTestRunner to draw spelling dots. This patch adds support for a header
+        at the top of test files, of the form <!-- webkit-test-runner [ spellCheckingDots=true ] --> which will cause
+        dots to be drawn.
+
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::resetStateToConsistentValues):
+        (WTR::updateTestOptionsFromTestHeader):
+        (WTR::TestController::platformResetStateToConsistentValues):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestOptions.h:
+        (WTR::TestOptions::hasSameInitializationOptions const):
+        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
+        (WTR::TestController::cocoaResetStateToConsistentValues):
+        * WebKitTestRunner/cocoa/TestRunnerWKWebView.h:
+        * WebKitTestRunner/ios/TestControllerIOS.mm:
+        (WTR::TestController::platformResetStateToConsistentValues):
+        * WebKitTestRunner/mac/TestControllerMac.mm:
+        (WTR::TestController::platformResetStateToConsistentValues):
+
 2018-11-06  Don Olmstead  <don.olmst...@sony.com>
 
         Feature flags not present for Visual Studio when using build-webkit

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2018-11-06 23:06:37 UTC (rev 237893)
@@ -926,7 +926,7 @@
 
     setHidden(false);
 
-    platformResetStateToConsistentValues();
+    platformResetStateToConsistentValues(options);
 
     m_shouldDecideNavigationPolicyAfterDelay = false;
     m_shouldDecideResponsePolicyAfterDelay = false;
@@ -1237,6 +1237,8 @@
             testOptions.runSingly = parseBooleanTestHeaderValue(value);
         else if (key == "shouldIgnoreMetaViewport")
             testOptions.shouldIgnoreMetaViewport = parseBooleanTestHeaderValue(value);
+        else if (key == "spellCheckingDots")
+            testOptions.shouldShowSpellCheckingDots = parseBooleanTestHeaderValue(value);
         pairStart = pairEnd + 1;
     }
 }
@@ -2649,7 +2651,7 @@
     return context;
 }
 
-void TestController::platformResetStateToConsistentValues()
+void TestController::platformResetStateToConsistentValues(const TestOptions&)
 {
 }
 

Modified: trunk/Tools/WebKitTestRunner/TestController.h (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/TestController.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -285,10 +285,10 @@
     void platformCreateWebView(WKPageConfigurationRef, const TestOptions&);
     static PlatformWebView* platformCreateOtherPage(PlatformWebView* parentView, WKPageConfigurationRef, const TestOptions&);
     void platformResetPreferencesToConsistentValues();
-    void platformResetStateToConsistentValues();
+    void platformResetStateToConsistentValues(const TestOptions&);
 #if PLATFORM(COCOA)
     void cocoaPlatformInitialize();
-    void cocoaResetStateToConsistentValues();
+    void cocoaResetStateToConsistentValues(const TestOptions&);
 #endif
     void platformConfigureViewForTest(const TestInvocation&);
     void platformWillRunTest(const TestInvocation&);

Modified: trunk/Tools/WebKitTestRunner/TestOptions.h (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/TestOptions.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/TestOptions.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -63,6 +63,7 @@
     bool runSingly { false };
     bool checkForWorldLeaks { false };
     bool shouldIgnoreMetaViewport { false };
+    bool shouldShowSpellCheckingDots { false };
 
     float deviceScaleFactor { 1 };
     Vector<String> overrideLanguages;
@@ -103,6 +104,7 @@
             || jscOptions != options.jscOptions
             || runSingly != options.runSingly
             || checkForWorldLeaks != options.checkForWorldLeaks
+            || shouldShowSpellCheckingDots != options.shouldShowSpellCheckingDots
             || shouldIgnoreMetaViewport != options.shouldIgnoreMetaViewport)
             return false;
 

Modified: trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm	2018-11-06 23:06:37 UTC (rev 237893)
@@ -203,7 +203,7 @@
         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:endDate];
 }
 
-void TestController::cocoaResetStateToConsistentValues()
+void TestController::cocoaResetStateToConsistentValues(const TestOptions& options)
 {
 #if WK_API_ENABLED
     __block bool doneRemoving = false;
@@ -213,10 +213,15 @@
     platformRunUntil(doneRemoving, noTimeout);
     [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
 
+
     if (auto* webView = mainWebView()) {
         TestRunnerWKWebView *platformView = webView->platformView();
         [platformView.configuration.userContentController _removeAllUserContentFilters];
         platformView._viewScale = 1;
+
+        // Toggle on before the test, and toggle off after the test.
+        if (options.shouldShowSpellCheckingDots)
+            [platformView toggleContinuousSpellChecking:nil];
     }
 #endif
 }

Modified: trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.h (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.h	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/cocoa/TestRunnerWKWebView.h	2018-11-06 23:06:37 UTC (rev 237893)
@@ -27,6 +27,10 @@
 
 #if WK_API_ENABLED
 
+@interface WKWebView(SpellChecking)
+- (IBAction)toggleContinuousSpellChecking:(id)sender;
+@end
+
 @interface TestRunnerWKWebView : WKWebView
 
 #if PLATFORM(IOS_FAMILY)

Modified: trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm	2018-11-06 23:06:37 UTC (rev 237893)
@@ -101,9 +101,9 @@
     WKPreferencesSetTextAutosizingEnabled(preferences, false);
 }
 
-void TestController::platformResetStateToConsistentValues()
+void TestController::platformResetStateToConsistentValues(const TestOptions& options)
 {
-    cocoaResetStateToConsistentValues();
+    cocoaResetStateToConsistentValues(options);
 
     [[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait animated:NO];
     

Modified: trunk/Tools/WebKitTestRunner/mac/TestControllerMac.mm (237892 => 237893)


--- trunk/Tools/WebKitTestRunner/mac/TestControllerMac.mm	2018-11-06 22:51:35 UTC (rev 237892)
+++ trunk/Tools/WebKitTestRunner/mac/TestControllerMac.mm	2018-11-06 23:06:37 UTC (rev 237893)
@@ -102,9 +102,9 @@
 {
 }
 
-void TestController::platformResetStateToConsistentValues()
+void TestController::platformResetStateToConsistentValues(const TestOptions& options)
 {
-    cocoaResetStateToConsistentValues();
+    cocoaResetStateToConsistentValues(options);
 
     while ([NSApp nextEventMatchingMask:NSEventMaskGesture | NSEventMaskScrollWheel untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]) {
         // Clear out (and ignore) any pending gesture and scroll wheel events.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to