https://bugs.webkit.org/show_bug.cgi?id=47237
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Nov 2010 05:49:57 +0000 (05:49 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 6 Nov 2010 05:49:57 +0000 (05:49 +0000)
Reviewed by Dan Bernstein and Simon Fraser.

Make selection work with vertical text.  This patch fixes a bug in the computation of lineTop.  For lines
with positive leading, lineTop was incorrectly including the top leading.  Since the flipping of lines
for "lr" and "bt" writing modes involved flipping using lineTop and lineBottom, an incorrect lineTop meant
that those modes were mis-rendering.  This is why the Japanese "lr" text examples have the first line smushed
too far against the border.

Fixing lineTop to no longer incorrectly include top leading has implications for editing.  I ended up
rewriting positionForPoint to exactly match selection, since that seemed to be the most intuitive
behavior.  I got rid of the verticalClickFudgeFactor and now just use selectionTop and selectionBottom
instead of lineTop and lineBottom.  I am pretty sure the code used selectionTop in a previous incarnation
anyway and that I moved away from it when I implemented lineTop and lineBottom.  The code then grew
more complicated from people trying to work with lineTop and lineBottom, but going back to selectionTop
and selectionBottom is the right behavior I think.  One editing test has been updated after this change
(editing/selection/after-line-break.html), and one DOM test has been changed to not hit test past the
bottom of a line (fast/dom/Document/CaretRangeFromPoint/basic.html).

I patched selection painting of InlineTextBoxes so that the leading going up to the next line box is used
for "lr" and "bt" modes instead of the previous box.  This makes sense for English text, but we may want
a different policy for Japanese text eventually (possibly just splitting the difference instead).  Leaving it
this way for now, and we can collect feedback on the design.

I rewrote all of the selection gap painting code to be writing-mode aware.  During the course of rewriting this
code I noticed a bug in the logicalLeftSelectionOffset and logicalRightSelectionOffset functions where there
was a coordinate space mismatch on a comparison.  Fixing this improves the repaint/selection-clear.html test.

Added new tests in fast/blockflow/.

WebCore:

* rendering/InlineFlowBox.cpp:
(WebCore::InlineFlowBox::placeBoxesInBlockDirection):
* rendering/InlineFlowBox.h:
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::selectionBottom):
(WebCore::InlineTextBox::paintSelection):
(WebCore::InlineTextBox::paintCompositionBackground):
(WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
(WebCore::InlineTextBox::paintTextMatchMarker):
* rendering/InlineTextBox.h:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::selectionGapRectsForRepaint):
(WebCore::RenderBlock::paintSelection):
(WebCore::clipOutPositionedObjects):
(WebCore::blockDirectionOffset):
(WebCore::inlineDirectionOffset):
(WebCore::RenderBlock::logicalRectToPhysicalRect):
(WebCore::RenderBlock::selectionGaps):
(WebCore::RenderBlock::inlineSelectionGaps):
(WebCore::RenderBlock::blockSelectionGaps):
(WebCore::RenderBlock::blockSelectionGap):
(WebCore::RenderBlock::logicalLeftSelectionGap):
(WebCore::RenderBlock::logicalRightSelectionGap):
(WebCore::RenderBlock::logicalLeftSelectionOffset):
(WebCore::RenderBlock::logicalRightSelectionOffset):
* rendering/RenderBlock.h:
* rendering/RenderBox.cpp:
(WebCore::RenderBox::flipForWritingMode):
* rendering/RenderBox.h:
(WebCore::RenderBox::logicalBottom):
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::alignBoxesInBlockDirection):
(WebCore::RootInlineBox::lineSelectionGap):
(WebCore::RootInlineBox::selectionTop):
(WebCore::RootInlineBox::selectionBottom):
* rendering/RootInlineBox.h:

LayoutTests:

* editing/selection/after-line-break-expected.txt:
* fast/blockflow/japanese-lr-selection.html: Added.
* fast/blockflow/japanese-rl-selection.html: Added.
* fast/dom/Document/CaretRangeFromPoint/basic.html:
* platform/mac/fast/blockflow/background-horizontal-bt-expected.checksum:
* platform/mac/fast/blockflow/background-horizontal-bt-expected.png:
* platform/mac/fast/blockflow/background-horizontal-bt-expected.txt:
* platform/mac/fast/blockflow/background-vertical-lr-expected.checksum:
* platform/mac/fast/blockflow/background-vertical-lr-expected.png:
* platform/mac/fast/blockflow/background-vertical-lr-expected.txt:
* platform/mac/fast/blockflow/border-image-horizontal-bt-expected.checksum:
* platform/mac/fast/blockflow/border-image-horizontal-bt-expected.png:
* platform/mac/fast/blockflow/border-image-horizontal-bt-expected.txt:
* platform/mac/fast/blockflow/border-image-vertical-lr-expected.checksum:
* platform/mac/fast/blockflow/border-image-vertical-lr-expected.png:
* platform/mac/fast/blockflow/border-image-vertical-lr-expected.txt:
* platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.checksum:
* platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.png:
* platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.txt:
* platform/mac/fast/blockflow/border-vertical-lr-expected.checksum:
* platform/mac/fast/blockflow/border-vertical-lr-expected.png:
* platform/mac/fast/blockflow/border-vertical-lr-expected.txt:
* platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.checksum:
* platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.png:
* platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.txt:
* platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.checksum:
* platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.png:
* platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.txt:
* platform/mac/fast/blockflow/japanese-lr-selection-expected.checksum: Added.
* platform/mac/fast/blockflow/japanese-lr-selection-expected.png: Added.
* platform/mac/fast/blockflow/japanese-lr-selection-expected.txt: Added.
* platform/mac/fast/blockflow/japanese-lr-text-expected.checksum:
* platform/mac/fast/blockflow/japanese-lr-text-expected.png:
* platform/mac/fast/blockflow/japanese-lr-text-expected.txt:
* platform/mac/fast/blockflow/japanese-rl-selection-expected.checksum: Added.
* platform/mac/fast/blockflow/japanese-rl-selection-expected.png: Added.
* platform/mac/fast/blockflow/japanese-rl-selection-expected.txt: Added.
* platform/mac/fast/repaint/selection-clear-expected.checksum:
* platform/mac/fast/repaint/selection-clear-expected.png:

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

51 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/selection/after-line-break-expected.txt
LayoutTests/fast/blockflow/japanese-lr-selection.html [new file with mode: 0644]
LayoutTests/fast/blockflow/japanese-rl-selection.html [new file with mode: 0644]
LayoutTests/fast/dom/Document/CaretRangeFromPoint/basic.html
LayoutTests/platform/mac/fast/blockflow/background-horizontal-bt-expected.checksum
LayoutTests/platform/mac/fast/blockflow/background-horizontal-bt-expected.png
LayoutTests/platform/mac/fast/blockflow/background-horizontal-bt-expected.txt
LayoutTests/platform/mac/fast/blockflow/background-vertical-lr-expected.checksum
LayoutTests/platform/mac/fast/blockflow/background-vertical-lr-expected.png
LayoutTests/platform/mac/fast/blockflow/background-vertical-lr-expected.txt
LayoutTests/platform/mac/fast/blockflow/border-image-horizontal-bt-expected.checksum
LayoutTests/platform/mac/fast/blockflow/border-image-horizontal-bt-expected.png
LayoutTests/platform/mac/fast/blockflow/border-image-horizontal-bt-expected.txt
LayoutTests/platform/mac/fast/blockflow/border-image-vertical-lr-expected.checksum
LayoutTests/platform/mac/fast/blockflow/border-image-vertical-lr-expected.png
LayoutTests/platform/mac/fast/blockflow/border-image-vertical-lr-expected.txt
LayoutTests/platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.checksum
LayoutTests/platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.png
LayoutTests/platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.txt
LayoutTests/platform/mac/fast/blockflow/border-vertical-lr-expected.checksum
LayoutTests/platform/mac/fast/blockflow/border-vertical-lr-expected.png
LayoutTests/platform/mac/fast/blockflow/border-vertical-lr-expected.txt
LayoutTests/platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.checksum
LayoutTests/platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.png
LayoutTests/platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.txt
LayoutTests/platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.checksum
LayoutTests/platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.png
LayoutTests/platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.txt
LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/japanese-lr-text-expected.checksum
LayoutTests/platform/mac/fast/blockflow/japanese-lr-text-expected.png
LayoutTests/platform/mac/fast/blockflow/japanese-lr-text-expected.txt
LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/repaint/selection-clear-expected.checksum
LayoutTests/platform/mac/fast/repaint/selection-clear-expected.png
WebCore/ChangeLog
WebCore/rendering/InlineFlowBox.cpp
WebCore/rendering/InlineFlowBox.h
WebCore/rendering/InlineTextBox.cpp
WebCore/rendering/InlineTextBox.h
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderBox.cpp
WebCore/rendering/RenderBox.h
WebCore/rendering/RootInlineBox.cpp
WebCore/rendering/RootInlineBox.h

index 5e3cdcc..0024a53 100644 (file)
@@ -1,3 +1,76 @@
+2010-11-05  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Dan Bernstein and Simon Fraser.
+
+        https://bugs.webkit.org/show_bug.cgi?id=47237
+        
+        Make selection work with vertical text.  This patch fixes a bug in the computation of lineTop.  For lines
+        with positive leading, lineTop was incorrectly including the top leading.  Since the flipping of lines
+        for "lr" and "bt" writing modes involved flipping using lineTop and lineBottom, an incorrect lineTop meant
+        that those modes were mis-rendering.  This is why the Japanese "lr" text examples have the first line smushed
+        too far against the border.
+        
+        Fixing lineTop to no longer incorrectly include top leading has implications for editing.  I ended up
+        rewriting positionForPoint to exactly match selection, since that seemed to be the most intuitive
+        behavior.  I got rid of the verticalClickFudgeFactor and now just use selectionTop and selectionBottom
+        instead of lineTop and lineBottom.  I am pretty sure the code used selectionTop in a previous incarnation
+        anyway and that I moved away from it when I implemented lineTop and lineBottom.  The code then grew
+        more complicated from people trying to work with lineTop and lineBottom, but going back to selectionTop
+        and selectionBottom is the right behavior I think.  One editing test has been updated after this change
+        (editing/selection/after-line-break.html), and one DOM test has been changed to not hit test past the
+        bottom of a line (fast/dom/Document/CaretRangeFromPoint/basic.html).
+        
+        I patched selection painting of InlineTextBoxes so that the leading going up to the next line box is used
+        for "lr" and "bt" modes instead of the previous box.  This makes sense for English text, but we may want
+        a different policy for Japanese text eventually (possibly just splitting the difference instead).  Leaving it
+        this way for now, and we can collect feedback on the design.
+        
+        I rewrote all of the selection gap painting code to be writing-mode aware.  During the course of rewriting this
+        code I noticed a bug in the logicalLeftSelectionOffset and logicalRightSelectionOffset functions where there
+        was a coordinate space mismatch on a comparison.  Fixing this improves the repaint/selection-clear.html test.
+
+        Added new tests in fast/blockflow/.
+
+        * editing/selection/after-line-break-expected.txt:
+        * fast/blockflow/japanese-lr-selection.html: Added.
+        * fast/blockflow/japanese-rl-selection.html: Added.
+        * fast/dom/Document/CaretRangeFromPoint/basic.html:
+        * platform/mac/fast/blockflow/background-horizontal-bt-expected.checksum:
+        * platform/mac/fast/blockflow/background-horizontal-bt-expected.png:
+        * platform/mac/fast/blockflow/background-horizontal-bt-expected.txt:
+        * platform/mac/fast/blockflow/background-vertical-lr-expected.checksum:
+        * platform/mac/fast/blockflow/background-vertical-lr-expected.png:
+        * platform/mac/fast/blockflow/background-vertical-lr-expected.txt:
+        * platform/mac/fast/blockflow/border-image-horizontal-bt-expected.checksum:
+        * platform/mac/fast/blockflow/border-image-horizontal-bt-expected.png:
+        * platform/mac/fast/blockflow/border-image-horizontal-bt-expected.txt:
+        * platform/mac/fast/blockflow/border-image-vertical-lr-expected.checksum:
+        * platform/mac/fast/blockflow/border-image-vertical-lr-expected.png:
+        * platform/mac/fast/blockflow/border-image-vertical-lr-expected.txt:
+        * platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.checksum:
+        * platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.png:
+        * platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.txt:
+        * platform/mac/fast/blockflow/border-vertical-lr-expected.checksum:
+        * platform/mac/fast/blockflow/border-vertical-lr-expected.png:
+        * platform/mac/fast/blockflow/border-vertical-lr-expected.txt:
+        * platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.checksum:
+        * platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.png:
+        * platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.txt:
+        * platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.checksum:
+        * platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.png:
+        * platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.txt:
+        * platform/mac/fast/blockflow/japanese-lr-selection-expected.checksum: Added.
+        * platform/mac/fast/blockflow/japanese-lr-selection-expected.png: Added.
+        * platform/mac/fast/blockflow/japanese-lr-selection-expected.txt: Added.
+        * platform/mac/fast/blockflow/japanese-lr-text-expected.checksum:
+        * platform/mac/fast/blockflow/japanese-lr-text-expected.png:
+        * platform/mac/fast/blockflow/japanese-lr-text-expected.txt:
+        * platform/mac/fast/blockflow/japanese-rl-selection-expected.checksum: Added.
+        * platform/mac/fast/blockflow/japanese-rl-selection-expected.png: Added.
+        * platform/mac/fast/blockflow/japanese-rl-selection-expected.txt: Added.
+        * platform/mac/fast/repaint/selection-clear-expected.checksum:
+        * platform/mac/fast/repaint/selection-clear-expected.png:
+
 2010-11-05  Adam Barth  <abarth@webkit.org>
 
         Reviewed by Eric Seidel.
index ee0cf00..8f15bbd 100644 (file)
@@ -1,6 +1,6 @@
 EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 5 of #text > DIV > BODY > HTML > #document to 5 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 6 of #text > DIV > BODY > HTML > #document to 6 of #text > DIV > BODY > HTML > #document toDOMRange:range from 6 of #text > DIV > BODY > HTML > #document to 6 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
diff --git a/LayoutTests/fast/blockflow/japanese-lr-selection.html b/LayoutTests/fast/blockflow/japanese-lr-selection.html
new file mode 100644 (file)
index 0000000..a65cbb6
--- /dev/null
@@ -0,0 +1,31 @@
+<!doctype html>
+<html style="border:10px solid maroon; -webkit-writing-mode:vertical-lr">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<style>
+body {
+    font-family: "HiraMinPro-W3";
+    font-size: 16pt;
+}
+</style>
+<script>
+function selectStuff()
+{
+    document.body.offsetLeft;
+    if (eventSender) {
+        eventSender.mouseMoveTo(40, 200);
+        eventSender.mouseDown();
+        eventSender.mouseMoveTo(40, 200);
+        eventSender.mouseMoveTo(400, 200);
+        eventSender.mouseUp();
+    }
+}
+</script>
+</head>
+<body style="border:5px solid black;" onload="selectStuff()">
+<div style="height:400px; margin-top:100px">
+せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますかならタイトルとアドレスだけでなく、訪問したウェブページのコンテンツからも検索することができます。せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますか ならタイトルとアドレスだけでなく、訪問したウェブページのコンテンツからも検索することができます。訪問したウェブページのコンテンツからも検索することができます。せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますか ならタイトルとアドレスだけでなく、訪問
+</div>
+
+
+</body>
diff --git a/LayoutTests/fast/blockflow/japanese-rl-selection.html b/LayoutTests/fast/blockflow/japanese-rl-selection.html
new file mode 100644 (file)
index 0000000..6491261
--- /dev/null
@@ -0,0 +1,31 @@
+<!doctype html>
+<html style="border:10px solid maroon; -webkit-writing-mode:vertical-rl">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<style>
+body {
+    font-family: "HiraMinPro-W3";
+    font-size: 16pt;
+}
+</style>
+<script>
+function selectStuff()
+{
+    document.body.offsetLeft;
+    if (eventSender) {
+        eventSender.mouseMoveTo(760, 200);
+        eventSender.mouseDown();
+        eventSender.mouseMoveTo(760, 200);
+        eventSender.mouseMoveTo(400, 200);
+        eventSender.mouseUp();
+    }
+}
+</script>
+</head>
+<body style="border:5px solid black;" onload="selectStuff()">
+<div style="height:400px; margin-top:100px">
+せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますかならタイトルとアドレスだけでなく、訪問したウェブページのコンテンツからも検索することができます。せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますか ならタイトルとアドレスだけでなく、訪問したウェブページのコンテンツからも検索することができます。訪問したウェブページのコンテンツからも検索することができます。せっかく見つけたすばらしい記事がどこにあったか忘れてしまった経験はありますか ならタイトルとアドレスだけでなく、訪問
+</div>
+
+
+</body>
index 299a375..244cf81 100644 (file)
             test(rect.left + rect.width, rect.top, "element.firstChild", "23");
 
             log("Testing lower left");
-            test(rect.left, rect.top + rect.height, "element.firstChild", "72");
+            test(rect.left, rect.top + rect.height - 1, "element.firstChild", "72");
             
             log("Testing lower right");
-            test(rect.left + rect.width, rect.top + rect.height, "element.firstChild", "95");
+            test(rect.left + rect.width, rect.top + rect.height - 1, "element.firstChild", "95");
 
             log("Testing somewhere in the middle");
             test((rect.left + rect.width) / 2, (rect.top + rect.height) / 2, "element.firstChild", "36");
index 54e2f25..11fed4f 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/background-horizontal-bt-expected.png and b/LayoutTests/platform/mac/fast/blockflow/background-horizontal-bt-expected.png differ
index 4310f70..b396711 100644 (file)
@@ -4,7 +4,7 @@ layer at (0,144) size 800x456
   RenderBlock {HTML} at (0,0) size 800x456
     RenderBody {BODY} at (8,8) size 784x440
       RenderInline {SPAN} at (0,0) size 50x268
-        RenderBlock {DIV} at (50,71) size 50x0
-        RenderBR {BR} at (100,50) size 0x98
-        RenderBlock {DIV} at (50,241) size 50x0
+        RenderBlock {DIV} at (50,107) size 50x0
+        RenderBR {BR} at (100,86) size 0x98
+        RenderBlock {DIV} at (50,277) size 50x0
       RenderText {#text} at (0,0) size 0x0
index 485776f..57e7928 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/background-vertical-lr-expected.png and b/LayoutTests/platform/mac/fast/blockflow/background-vertical-lr-expected.png differ
index 89c81a8..a547bc2 100644 (file)
@@ -4,7 +4,7 @@ layer at (0,0) size 456x600
   RenderBlock {HTML} at (0,0) size 456x600
     RenderBody {BODY} at (8,8) size 440x584
       RenderInline {SPAN} at (0,0) size 268x50
-        RenderBlock {DIV} at (71,50) size 0x50
-        RenderBR {BR} at (50,100) size 98x0
-        RenderBlock {DIV} at (241,50) size 0x50
+        RenderBlock {DIV} at (107,50) size 0x50
+        RenderBR {BR} at (86,100) size 98x0
+        RenderBlock {DIV} at (277,50) size 0x50
       RenderText {#text} at (0,0) size 0x0
index 794bd71..590cf38 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/border-image-horizontal-bt-expected.png and b/LayoutTests/platform/mac/fast/blockflow/border-image-horizontal-bt-expected.png differ
index cfbc49c..6585479 100644 (file)
@@ -4,7 +4,7 @@ layer at (0,140) size 800x460
   RenderBlock {HTML} at (0,0) size 800x460
     RenderBody {BODY} at (8,8) size 784x444
       RenderInline {SPAN} at (0,0) size 80x323 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
-        RenderBlock {DIV} at (101,102) size 25x0
-        RenderBR {BR} at (126,80) size 0x100
-        RenderBlock {DIV} at (50,274) size 50x0
+        RenderBlock {DIV} at (101,117) size 25x0
+        RenderBR {BR} at (126,95) size 0x100
+        RenderBlock {DIV} at (50,289) size 50x0
       RenderText {#text} at (0,0) size 0x0
index c80f8e9..1bf94cc 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/border-image-vertical-lr-expected.png and b/LayoutTests/platform/mac/fast/blockflow/border-image-vertical-lr-expected.png differ
index 0d829c5..787068b 100644 (file)
@@ -4,7 +4,7 @@ layer at (0,0) size 460x600
   RenderBlock {HTML} at (0,0) size 460x600
     RenderBody {BODY} at (8,8) size 444x584
       RenderInline {SPAN} at (0,0) size 323x80 [border: (21px none #000000) (30px none #000000) (21px none #000000)]
-        RenderBlock {DIV} at (93,101) size 0x25
-        RenderBR {BR} at (71,126) size 100x0
-        RenderBlock {DIV} at (265,50) size 0x50
+        RenderBlock {DIV} at (99,101) size 0x25
+        RenderBR {BR} at (77,126) size 100x0
+        RenderBlock {DIV} at (271,50) size 0x50
       RenderText {#text} at (0,0) size 0x0
index 8729107..25be605 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.png and b/LayoutTests/platform/mac/fast/blockflow/border-radius-clipping-vertical-lr-expected.png differ
index 5a3715c..95741e5 100644 (file)
@@ -7,7 +7,7 @@ layer at (0,0) size 785x621
         RenderInline {SPAN} at (0,0) size 137x613 [bgcolor=#0000FF]
           RenderText {#text} at (0,0) size 0x0
           RenderInline {SPAN} at (0,0) size 137x613 [bgcolor=#FFFFE0] [border: (5px solid #008000)]
-            RenderText {#text} at (5,35) size 127x613
-              text run at (5,35) width 578: "This sentence is too long to fit"
-              text run at (77,0) width 302: "on a single line."
+            RenderText {#text} at (8,35) size 127x613
+              text run at (8,35) width 578: "This sentence is too long to fit"
+              text run at (80,0) width 302: "on a single line."
         RenderText {#text} at (0,0) size 0x0
index 482aef0..dffc9f2 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/border-vertical-lr-expected.png and b/LayoutTests/platform/mac/fast/blockflow/border-vertical-lr-expected.png differ
index d074c62..c1ae950 100644 (file)
@@ -4,22 +4,22 @@ layer at (0,0) size 772x600
   RenderBlock {HTML} at (0,0) size 772x600
     RenderBody {BODY} at (8,8) size 756x584
       RenderInline {SPAN} at (0,0) size 218x554 [border: (2px solid #000000)]
-        RenderText {#text} at (4,4) size 210x554
-          text run at (4,4) width 550: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}"
-          text run at (67,0) width 550: "\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}"
-          text run at (130,0) width 550: "\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}"
-          text run at (193,0) width 170: "\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}"
-      RenderText {#text} at (193,174) size 21x7
-        text run at (193,174) width 7: " "
+        RenderText {#text} at (21,4) size 210x554
+          text run at (21,4) width 550: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}"
+          text run at (84,0) width 550: "\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}"
+          text run at (147,0) width 550: "\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}"
+          text run at (210,0) width 170: "\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}"
+      RenderText {#text} at (210,174) size 21x7
+        text run at (210,174) width 7: " "
       RenderBR {BR} at (0,0) size 0x0
-      RenderBR {BR} at (252,0) size 21x0
+      RenderBR {BR} at (273,0) size 21x0
       RenderInline {SPAN} at (0,0) size 413x558 [border: (5px solid #000000)]
-        RenderText {#text} at (322,7) size 399x558
-          text run at (322,7) width 550: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}"
-          text run at (385,0) width 558: "\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}"
-          text run at (448,0) width 550: "\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}"
-          text run at (511,0) width 550: "\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}"
-          text run at (574,0) width 550: "\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}"
-          text run at (637,0) width 558: "\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}"
-          text run at (700,0) width 381: "\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+        RenderText {#text} at (336,7) size 399x558
+          text run at (336,7) width 550: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}"
+          text run at (399,0) width 558: "\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}"
+          text run at (462,0) width 550: "\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}"
+          text run at (525,0) width 550: "\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}"
+          text run at (588,0) width 550: "\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}"
+          text run at (651,0) width 558: "\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}"
+          text run at (714,0) width 381: "\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
       RenderText {#text} at (0,0) size 0x0
index c4ff566..8edb90a 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.png and b/LayoutTests/platform/mac/fast/blockflow/box-shadow-horizontal-bt-expected.png differ
index 78ad9f4..623ffe9 100644 (file)
@@ -5,13 +5,13 @@ layer at (0,0) size 800x600
     RenderBody {BODY} at (8,8) size 784x584
       RenderBlock {DIV} at (0,0) size 600x144
         RenderInline {SPAN} at (0,0) size 598x137 [bgcolor=#FFFFE0] [border: (5px solid #008000)]
-          RenderText {#text} at (21,5) size 578x127
-            text run at (21,5) width 578: "This sentence is too long to fit"
-            text run at (139,77) width 302: "on a single line."
+          RenderText {#text} at (21,8) size 578x127
+            text run at (21,8) width 578: "This sentence is too long to fit"
+            text run at (139,80) width 302: "on a single line."
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {DIV} at (0,194) size 600x144
         RenderInline {SPAN} at (0,0) size 598x137 [bgcolor=#FFFFE0] [border: (5px solid #008000)]
-          RenderText {#text} at (21,5) size 578x127
-            text run at (21,5) width 578: "This sentence is too long to fit"
-            text run at (139,77) width 302: "on a single line."
+          RenderText {#text} at (21,8) size 578x127
+            text run at (21,8) width 578: "This sentence is too long to fit"
+            text run at (139,80) width 302: "on a single line."
         RenderText {#text} at (0,0) size 0x0
index 1876c1a..b377189 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.png and b/LayoutTests/platform/mac/fast/blockflow/box-shadow-vertical-lr-expected.png differ
index f47392c..9637dce 100644 (file)
@@ -5,13 +5,13 @@ layer at (0,0) size 785x608
     RenderBody {BODY} at (8,8) size 769x584
       RenderBlock {DIV} at (0,0) size 144x600
         RenderInline {SPAN} at (0,0) size 137x598 [bgcolor=#FFFFE0] [border: (5px solid #008000)]
-          RenderText {#text} at (5,21) size 127x578
-            text run at (5,21) width 578: "This sentence is too long to fit"
-            text run at (77,139) width 302: "on a single line."
+          RenderText {#text} at (8,21) size 127x578
+            text run at (8,21) width 578: "This sentence is too long to fit"
+            text run at (80,139) width 302: "on a single line."
         RenderText {#text} at (0,0) size 0x0
       RenderBlock {DIV} at (194,0) size 144x600
         RenderInline {SPAN} at (0,0) size 137x598 [bgcolor=#FFFFE0] [border: (5px solid #008000)]
-          RenderText {#text} at (5,21) size 127x578
-            text run at (5,21) width 578: "This sentence is too long to fit"
-            text run at (77,139) width 302: "on a single line."
+          RenderText {#text} at (8,21) size 127x578
+            text run at (8,21) width 578: "This sentence is too long to fit"
+            text run at (80,139) width 302: "on a single line."
         RenderText {#text} at (0,0) size 0x0
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.checksum b/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.checksum
new file mode 100644 (file)
index 0000000..9a642a6
--- /dev/null
@@ -0,0 +1 @@
+b0da59360a5489491f6853c98526700d
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.png b/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.png
new file mode 100644 (file)
index 0000000..e8c4e23
Binary files /dev/null and b/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.txt b/LayoutTests/platform/mac/fast/blockflow/japanese-lr-selection-expected.txt
new file mode 100644 (file)
index 0000000..477195b
--- /dev/null
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 526x600
+  RenderBlock {HTML} at (0,0) size 526x600 [border: (10px solid #800000)]
+    RenderBody {BODY} at (18,18) size 490x564 [border: (5px solid #000000)]
+      RenderBlock {DIV} at (5,105) size 480x400
+        RenderText {#text} at (5,0) size 469x381
+          text run at (5,0) width 381: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}"
+          text run at (37,0) width 381: "\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}"
+          text run at (69,0) width 360: "\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}"
+          text run at (101,0) width 381: "\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}"
+          text run at (133,0) width 381: "\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}"
+          text run at (165,0) width 381: "\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}"
+          text run at (197,0) width 360: "\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}"
+          text run at (229,0) width 381: "\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}"
+          text run at (261,0) width 381: "\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}"
+          text run at (293,0) width 381: "\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}"
+          text run at (325,0) width 381: "\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}"
+          text run at (357,0) width 381: "\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}"
+          text run at (389,0) width 381: "\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}"
+          text run at (421,0) width 368: "\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}"
+          text run at (453,0) width 233: "\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+selection start: position 5 of child 0 {#text} of child 1 {DIV} of body
+selection end:   position 202 of child 0 {#text} of child 1 {DIV} of body
index add74db..ae39877 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/blockflow/japanese-lr-text-expected.png and b/LayoutTests/platform/mac/fast/blockflow/japanese-lr-text-expected.png differ
index c60ae6d..57ae75b 100644 (file)
@@ -3,15 +3,15 @@ layer at (0,0) size 800x600
 layer at (0,0) size 398x600
   RenderBlock {HTML} at (0,0) size 398x600 [border: (10px solid #800000)]
     RenderBody {BODY} at (18,18) size 362x564 [border: (5px solid #000000)]
-      RenderText {#text} at (5,5) size 341x529
-        text run at (5,5) width 529: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}"
-        text run at (37,5) width 529: "\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}"
-        text run at (69,5) width 529: "\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}"
-        text run at (101,5) width 529: "\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}"
-        text run at (133,5) width 508: "\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}"
-        text run at (165,5) width 508: "\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}"
-        text run at (197,5) width 529: "\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}"
-        text run at (229,5) width 529: "\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}"
-        text run at (261,5) width 508: "\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}"
-        text run at (293,5) width 515: "\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}"
-        text run at (325,5) width 297: "\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+      RenderText {#text} at (10,5) size 341x529
+        text run at (10,5) width 529: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}"
+        text run at (42,5) width 529: "\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}"
+        text run at (74,5) width 529: "\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}"
+        text run at (106,5) width 529: "\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}"
+        text run at (138,5) width 508: "\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}"
+        text run at (170,5) width 508: "\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}"
+        text run at (202,5) width 529: "\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}"
+        text run at (234,5) width 529: "\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}"
+        text run at (266,5) width 508: "\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}"
+        text run at (298,5) width 515: "\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}"
+        text run at (330,5) width 297: "\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.checksum b/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.checksum
new file mode 100644 (file)
index 0000000..18fcc42
--- /dev/null
@@ -0,0 +1 @@
+52d2c57720a041392b55af6a464aa4a0
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.png b/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.png
new file mode 100644 (file)
index 0000000..67593d1
Binary files /dev/null and b/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.txt b/LayoutTests/platform/mac/fast/blockflow/japanese-rl-selection-expected.txt
new file mode 100644 (file)
index 0000000..65c9dff
--- /dev/null
@@ -0,0 +1,24 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (274,0) size 526x600
+  RenderBlock {HTML} at (0,0) size 526x600 [border: (10px solid #800000)]
+    RenderBody {BODY} at (18,18) size 490x564 [border: (5px solid #000000)]
+      RenderBlock {DIV} at (5,105) size 480x400
+        RenderText {#text} at (5,0) size 469x381
+          text run at (5,0) width 381: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}"
+          text run at (37,0) width 381: "\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}"
+          text run at (69,0) width 360: "\x{3059}\x{304B}\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}"
+          text run at (101,0) width 381: "\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}"
+          text run at (133,0) width 381: "\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}"
+          text run at (165,0) width 381: "\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}"
+          text run at (197,0) width 360: "\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}"
+          text run at (229,0) width 381: "\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}"
+          text run at (261,0) width 381: "\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}"
+          text run at (293,0) width 381: "\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}"
+          text run at (325,0) width 381: "\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}"
+          text run at (357,0) width 381: "\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}"
+          text run at (389,0) width 381: "\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}"
+          text run at (421,0) width 368: "\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}"
+          text run at (453,0) width 233: "\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+selection start: position 5 of child 0 {#text} of child 1 {DIV} of body
+selection end:   position 202 of child 0 {#text} of child 1 {DIV} of body
index 83e5296..32b57d0 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/repaint/selection-clear-expected.png and b/LayoutTests/platform/mac/fast/repaint/selection-clear-expected.png differ
index 1418cda..274f8c9 100644 (file)
@@ -1,3 +1,73 @@
+2010-11-05  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Dan Bernstein and Simon Fraser.
+
+        https://bugs.webkit.org/show_bug.cgi?id=47237
+        
+        Make selection work with vertical text.  This patch fixes a bug in the computation of lineTop.  For lines
+        with positive leading, lineTop was incorrectly including the top leading.  Since the flipping of lines
+        for "lr" and "bt" writing modes involved flipping using lineTop and lineBottom, an incorrect lineTop meant
+        that those modes were mis-rendering.  This is why the Japanese "lr" text examples have the first line smushed
+        too far against the border.
+        
+        Fixing lineTop to no longer incorrectly include top leading has implications for editing.  I ended up
+        rewriting positionForPoint to exactly match selection, since that seemed to be the most intuitive
+        behavior.  I got rid of the verticalClickFudgeFactor and now just use selectionTop and selectionBottom
+        instead of lineTop and lineBottom.  I am pretty sure the code used selectionTop in a previous incarnation
+        anyway and that I moved away from it when I implemented lineTop and lineBottom.  The code then grew
+        more complicated from people trying to work with lineTop and lineBottom, but going back to selectionTop
+        and selectionBottom is the right behavior I think.  One editing test has been updated after this change
+        (editing/selection/after-line-break.html), and one DOM test has been changed to not hit test past the
+        bottom of a line (fast/dom/Document/CaretRangeFromPoint/basic.html).
+        
+        I patched selection painting of InlineTextBoxes so that the leading going up to the next line box is used
+        for "lr" and "bt" modes instead of the previous box.  This makes sense for English text, but we may want
+        a different policy for Japanese text eventually (possibly just splitting the difference instead).  Leaving it
+        this way for now, and we can collect feedback on the design.
+        
+        I rewrote all of the selection gap painting code to be writing-mode aware.  During the course of rewriting this
+        code I noticed a bug in the logicalLeftSelectionOffset and logicalRightSelectionOffset functions where there
+        was a coordinate space mismatch on a comparison.  Fixing this improves the repaint/selection-clear.html test.
+
+        Added new tests in fast/blockflow/.
+
+        * rendering/InlineFlowBox.cpp:
+        (WebCore::InlineFlowBox::placeBoxesInBlockDirection):
+        * rendering/InlineFlowBox.h:
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::selectionBottom):
+        (WebCore::InlineTextBox::paintSelection):
+        (WebCore::InlineTextBox::paintCompositionBackground):
+        (WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
+        (WebCore::InlineTextBox::paintTextMatchMarker):
+        * rendering/InlineTextBox.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::selectionGapRectsForRepaint):
+        (WebCore::RenderBlock::paintSelection):
+        (WebCore::clipOutPositionedObjects):
+        (WebCore::blockDirectionOffset):
+        (WebCore::inlineDirectionOffset):
+        (WebCore::RenderBlock::logicalRectToPhysicalRect):
+        (WebCore::RenderBlock::selectionGaps):
+        (WebCore::RenderBlock::inlineSelectionGaps):
+        (WebCore::RenderBlock::blockSelectionGaps):
+        (WebCore::RenderBlock::blockSelectionGap):
+        (WebCore::RenderBlock::logicalLeftSelectionGap):
+        (WebCore::RenderBlock::logicalRightSelectionGap):
+        (WebCore::RenderBlock::logicalLeftSelectionOffset):
+        (WebCore::RenderBlock::logicalRightSelectionOffset):
+        * rendering/RenderBlock.h:
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::flipForWritingMode):
+        * rendering/RenderBox.h:
+        (WebCore::RenderBox::logicalBottom):
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::alignBoxesInBlockDirection):
+        (WebCore::RootInlineBox::lineSelectionGap):
+        (WebCore::RootInlineBox::selectionTop):
+        (WebCore::RootInlineBox::selectionBottom):
+        * rendering/RootInlineBox.h:
+
 2010-11-05  Simon Fraser  <simon.fraser@apple.com>
 
         Just put things back the way they were. Too many mysterious linker errors.
index 1187a8b..8525673 100644 (file)
@@ -480,7 +480,7 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
     }
 }
 
-void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom)
+void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop)
 {
     if (isRootInlineBox())
         setLogicalTop(top + maxAscent - baselinePosition()); // Place our root box.
@@ -493,7 +493,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs
         // line-height).
         bool isInlineFlow = curr->isInlineFlowBox();
         if (isInlineFlow)
-            static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom);
+            static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop);
 
         bool childAffectsTopBottomPos = true;
         if (curr->logicalTop() == PositionTop)
@@ -525,7 +525,11 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs
 
         if (childAffectsTopBottomPos) {
             int boxHeight = curr->logicalHeight();
-            lineTop = min(lineTop, newLogicalTop);
+            if (!setLineTop) {
+                setLineTop = true;
+                lineTop = newLogicalTop;
+            } else
+                lineTop = min(lineTop, newLogicalTop);
             lineBottom = max(lineBottom, newLogicalTop + boxHeight);
         }
     }
@@ -535,7 +539,11 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs
         setLogicalTop(logicalTop() + baselinePosition() - font.ascent());
         
         if (hasTextChildren() || strictMode) {
-            lineTop = min(lineTop, logicalTop());
+            if (!setLineTop) {
+                setLineTop = true;
+                lineTop = logicalTop();
+            } else
+                lineTop = min(lineTop, logicalTop());
             lineBottom = max(lineBottom, logicalTop() + logicalHeight());
         }
         
index 79a3e29..be6dfd2 100644 (file)
@@ -158,7 +158,7 @@ public:
                                   int& maxAscent, int& maxDescent, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
     void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
                                    int maxPositionTop, int maxPositionBottom);
-    void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom);
+    void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop);
     void flipLinesInBlockDirection(int lineTop, int lineBottom);
     void computeBlockDirectionOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
 
index 1193288..9c96cc6 100644 (file)
@@ -64,6 +64,11 @@ int InlineTextBox::selectionTop()
     return root()->selectionTop();
 }
 
+int InlineTextBox::selectionBottom()
+{
+    return root()->selectionBottom();
+}
+
 int InlineTextBox::selectionHeight()
 {
     return root()->selectionHeight();
@@ -682,7 +687,7 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const IntPoint& box
         ePos = length;
     }
 
-    int deltaY = logicalTop() - selectionTop();
+    int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
     int selHeight = selectionHeight();
     IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
     context->clip(IntRect(localOrigin, IntSize(m_logicalWidth, selHeight)));
@@ -707,7 +712,7 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const I
     
     updateGraphicsContext(context, c, c, 0, style->colorSpace()); // Don't draw text at all!
 
-    int deltaY = logicalTop() - selectionTop();
+    int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
     int selHeight = selectionHeight();
     IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
     context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd,
@@ -869,7 +874,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const IntP
             endPosition = min<int>(endPosition, m_truncation);
 
         // Calculate start & width
-        int deltaY = logicalTop() - selectionTop();
+        int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
         int selHeight = selectionHeight();
         IntPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
         TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
@@ -911,7 +916,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const IntPoint& bo
 {
     // Use same y positioning and height as for selection, so that when the selection and this highlight are on
     // the same word there are no pieces sticking out.
-    int deltaY = logicalTop() - selectionTop();
+    int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
     int selHeight = selectionHeight();
 
     int sPos = max(marker.startOffset - m_start, (unsigned)0);
index a5a77f0..e72d625 100644 (file)
@@ -74,8 +74,9 @@ public:
     virtual int lineHeight() const;
 
 private:
-    virtual int selectionTop();
-    virtual int selectionHeight();
+    int selectionTop();
+    int selectionBottom();
+    int selectionHeight();
 
 public:
     virtual IntRect calculateBoundaries() const { return IntRect(x(), y(), logicalWidth(), logicalHeight()); }
index cad47f7..0d6a560 100644 (file)
@@ -56,10 +56,6 @@ using namespace Unicode;
 
 namespace WebCore {
 
-// Number of pixels to allow as a fudge factor when clicking above or below a line.
-// clicking up to verticalLineClickFudgeFactor pixels above a line will correspond to the closest point on the line.   
-static const int verticalLineClickFudgeFactor = 3;
-
 using namespace HTMLNames;
 
 typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
@@ -2557,7 +2553,7 @@ GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintC
     int lastLeft = logicalLeftSelectionOffset(this, lastTop);
     int lastRight = logicalRightSelectionOffset(this, lastTop);
     
-    return fillSelectionGaps(this, offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), offsetFromRepaintContainer.x(), offsetFromRepaintContainer.y(), lastTop, lastLeft, lastRight);
+    return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
 }
 
 void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
@@ -2567,7 +2563,7 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
         int lastLeft = logicalLeftSelectionOffset(this, lastTop);
         int lastRight = logicalRightSelectionOffset(this, lastTop);
         paintInfo.context->save();
-        IntRect gapRectsBounds = fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &paintInfo);
+        IntRect gapRectsBounds = selectionGaps(this, IntPoint(tx, ty), IntSize(), lastTop, lastLeft, lastRight, &paintInfo);
         if (!gapRectsBounds.isEmpty()) {
             if (RenderLayer* layer = enclosingLayer()) {
                 gapRectsBounds.move(IntSize(-tx, -ty));
@@ -2583,8 +2579,7 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
     }
 }
 
-#ifndef BUILDING_ON_TIGER
-static void clipOutPositionedObjects(const PaintInfo* paintInfo, int tx, int ty, RenderBlock::PositionedObjectsListHashSet* positionedObjects)
+static void clipOutPositionedObjects(const PaintInfo* paintInfo, const IntPoint& offset, RenderBlock::PositionedObjectsListHashSet* positionedObjects)
 {
     if (!positionedObjects)
         return;
@@ -2592,33 +2587,58 @@ static void clipOutPositionedObjects(const PaintInfo* paintInfo, int tx, int ty,
     RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
     for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
         RenderBox* r = *it;
-        paintInfo->context->clipOut(IntRect(tx + r->x(), ty + r->y(), r->width(), r->height()));
+        paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
     }
 }
-#endif
 
-GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
-                                        int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+static int blockDirectionOffset(RenderBlock* rootBlock, const IntSize& offsetFromRootBlock)
+{
+    return rootBlock->style()->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
+}
+
+static int inlineDirectionOffset(RenderBlock* rootBlock, const IntSize& offsetFromRootBlock)
+{
+    return rootBlock->style()->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
+}
+
+IntRect RenderBlock::logicalRectToPhysicalRect(const IntPoint& rootBlockPhysicalPosition, const IntRect& logicalRect)
+{
+    IntRect result;
+    if (style()->isHorizontalWritingMode())
+        result = logicalRect;
+    else
+        result = IntRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
+    flipForWritingMode(result);
+    result.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
+    return result;
+}
+
+GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                    int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
 {
-#ifndef BUILDING_ON_TIGER
     // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
     // Clip out floating and positioned objects when painting selection gaps.
     if (paintInfo) {
         // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
-        clipOutPositionedObjects(paintInfo, tx, ty, m_positionedObjects);
+        IntRect flippedBlockRect = IntRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
+        rootBlock->flipForWritingMode(flippedBlockRect);
+        flippedBlockRect.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
+        clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), m_positionedObjects);
         if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
             for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
-                clipOutPositionedObjects(paintInfo, cb->x(), cb->y(), cb->m_positionedObjects);
+                clipOutPositionedObjects(paintInfo, IntPoint(cb->x(), cb->y()), cb->m_positionedObjects); // FIXME: Not right for flipped writing modes.
         if (m_floatingObjects) {
             for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); it.current(); ++it) {
                 FloatingObject* r = it.current();
-                paintInfo->context->clipOut(IntRect(tx + r->left() + r->m_renderer->marginLeft(), 
-                                                    ty + r->top() + r->m_renderer->marginTop(),
-                                                    r->m_renderer->width(), r->m_renderer->height()));
+                IntRect floatBox = IntRect(offsetFromRootBlock.width() + r->left() + r->m_renderer->marginLeft(),
+                                           offsetFromRootBlock.height() + r->top() + r->m_renderer->marginTop(),
+                                           r->m_renderer->width(), r->m_renderer->height());
+                rootBlock->flipForWritingMode(floatBox);
+                floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
+                paintInfo->context->clipOut(floatBox);
             }
         }
     }
-#endif
 
     // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
     // fixed).
@@ -2628,26 +2648,26 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
 
     if (hasColumns() || hasTransform() || style()->columnSpan()) {
         // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
-        lastTop = (ty - blockY) + height();
-        lastLeft = logicalLeftSelectionOffset(rootBlock, height());
-        lastRight = logicalRightSelectionOffset(rootBlock, height());
+        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
+        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
+        lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
         return result;
     }
 
     if (childrenInline())
-        result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
+        result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
     else
-        result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
+        result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
 
     // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
     if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
-        result.uniteCenter(fillBlockSelectionGap(lastTop, lastLeft, lastRight, ty + height(),
-                                                 rootBlock, blockX, blockY, paintInfo));
+        result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                             logicalHeight(), paintInfo));
     return result;
 }
 
-GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, 
-                                              int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                          int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
 {
     GapRects result;
 
@@ -2655,11 +2675,11 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX
 
     if (!firstLineBox()) {
         if (containsStart) {
-            // Go ahead and update our lastY to be the bottom of the block.  <hr>s or empty blocks with height can trip this
+            // Go ahead and update our lastLogicalTop to be the bottom of the block.  <hr>s or empty blocks with height can trip this
             // case.
-            lastTop = (ty - blockY) + height();
-            lastLeft = logicalLeftSelectionOffset(rootBlock, height());
-            lastRight = logicalRightSelectionOffset(rootBlock, height());
+            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
+            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
+            lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
         }
         return result;
     }
@@ -2675,11 +2695,15 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX
 
         if (!containsStart && !lastSelectedLine &&
             selectionState() != SelectionStart && selectionState() != SelectionBoth)
-            result.uniteCenter(fillBlockSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
-                                                     rootBlock, blockX, blockY, paintInfo));
-
-        if (!paintInfo || (ty + selTop < paintInfo->rect.bottom() && ty + selTop + selHeight > paintInfo->rect.y()))
-            result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo));
+            result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                                 selTop, paintInfo));
+        
+        IntRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
+        logicalRect.move(style()->isHorizontalWritingMode() ? offsetFromRootBlock : IntSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
+        IntRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
+        if (!paintInfo || (style()->isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.bottom() && physicalRect.bottom() > paintInfo->rect.y())
+            || (!style()->isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.right() && physicalRect.right() > paintInfo->rect.x()))
+            result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
 
         lastSelectedLine = curr;
     }
@@ -2690,15 +2714,15 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX
 
     if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
         // Go ahead and update our lastY to be the bottom of the last selected line.
-        lastTop = (ty - blockY) + lastSelectedLine->selectionBottom();
-        lastLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
-        lastRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
+        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
+        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
+        lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
     }
     return result;
 }
 
-GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
-                                             int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
+GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                         int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
 {
     GapRects result;
 
@@ -2728,8 +2752,8 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
             // We need to fill the vertical gap above this object.
             if (childState == SelectionEnd || childState == SelectionInside)
                 // Fill the gap above the object.
-                result.uniteCenter(fillBlockSelectionGap(lastTop, lastLeft, lastRight, 
-                                                         ty + curr->y(), rootBlock, blockX, blockY, paintInfo));
+                result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                                     curr->logicalTop(), paintInfo));
 
             // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
             // our object.  We know this if the selection did not end inside our object.
@@ -2741,82 +2765,72 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
             getSelectionGapInfo(childState, leftGap, rightGap);
 
             if (leftGap)
-                result.uniteLeft(fillLogicalLeftSelectionGap(this, curr->x(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+                result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
             if (rightGap)
-                result.uniteRight(fillLogicalRightSelectionGap(this, curr->x() + curr->width(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+                result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
 
-            // Update lastTop to be just underneath the object.  lastLeft and lastRight extend as far as
+            // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight extend as far as
             // they can without bumping into floating or positioned objects.  Ideally they will go right up
             // to the border of the root selection block.
-            lastTop = (ty - blockY) + (curr->y() + curr->height());
-            lastLeft = logicalLeftSelectionOffset(rootBlock, curr->y() + curr->height());
-            lastRight = logicalRightSelectionOffset(rootBlock, curr->y() + curr->height());
+            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
+            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
+            lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
         } else if (childState != SelectionNone)
             // We must be a block that has some selected object inside it.  Go ahead and recur.
-            result.unite(toRenderBlock(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->x(), ty + curr->y(), 
-                                                                            lastTop, lastLeft, lastRight, paintInfo));
+            result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, IntSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()), 
+                                                            lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
     }
     return result;
 }
 
-IntRect RenderBlock::fillLineSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo* paintInfo)
-{
-    if (width <= 0 || height <= 0)
-        return IntRect();
-    IntRect gapRect(xPos, yPos, width, height);
-    if (paintInfo && selObj->style()->visibility() == VISIBLE)
-        paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
-    return gapRect;
-}
-
-IntRect RenderBlock::fillBlockSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
-                                           int blockX, int blockY, const PaintInfo* paintInfo)
+IntRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                       int lastLogicalTop, int lastLogicalLeft, int lastLogicalRight, int logicalBottom, const PaintInfo* paintInfo)
 {
-    int top = blockY + lastTop;
-    int height = bottomY - top;
-    if (height <= 0)
+    int logicalTop = lastLogicalTop;
+    int logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
+    if (logicalHeight <= 0)
         return IntRect();
 
     // Get the selection offsets for the bottom of the gap
-    int left = blockX + max(lastLeft, logicalLeftSelectionOffset(rootBlock, bottomY));
-    int right = blockX + min(lastRight, logicalRightSelectionOffset(rootBlock, bottomY));
-    int width = right - left;
-    if (width <= 0)
+    int logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
+    int logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
+    int logicalWidth = logicalRight - logicalLeft;
+    if (logicalWidth <= 0)
         return IntRect();
 
-    IntRect gapRect(left, top, width, height);
+    IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
     if (paintInfo)
         paintInfo->context->fillRect(gapRect, selectionBackgroundColor(), style()->colorSpace());
     return gapRect;
 }
 
-IntRect RenderBlock::fillLogicalLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
-                                                 int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
+IntRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                             RenderObject* selObj, int logicalLeft, int logicalTop, int logicalHeight, const PaintInfo* paintInfo)
 {
-    int top = yPos + ty;
-    int left = blockX + max(logicalLeftSelectionOffset(rootBlock, yPos), logicalLeftSelectionOffset(rootBlock, yPos + height));
-    int right = min(xPos + tx, blockX + min(logicalRightSelectionOffset(rootBlock, yPos), logicalRightSelectionOffset(rootBlock, yPos + height)));
-    int width = right - left;
-    if (width <= 0)
+    int rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
+    int rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
+    int rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalLeft, min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
+    int rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
+    if (rootBlockLogicalWidth <= 0)
         return IntRect();
 
-    IntRect gapRect(left, top, width, height);
+    IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
     if (paintInfo)
         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
     return gapRect;
 }
 
-IntRect RenderBlock::fillLogicalRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
-                                                  int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
+IntRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                              RenderObject* selObj, int logicalRight, int logicalTop, int logicalHeight, const PaintInfo* paintInfo)
 {
-    int left = max(xPos + tx, blockX + max(logicalLeftSelectionOffset(rootBlock, yPos), logicalLeftSelectionOffset(rootBlock, yPos + height)));
-    int top = yPos + ty;
-    int right = blockX + min(logicalRightSelectionOffset(rootBlock, yPos), logicalRightSelectionOffset(rootBlock, yPos + height));
-    int width = right - left;
-    if (width <= 0)
+    int rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
+    int rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalRight, max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
+    int rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
+    int rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
+    if (rootBlockLogicalWidth <= 0)
         return IntRect();
 
-    IntRect gapRect(left, top, width, height);
+    IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
     if (paintInfo)
         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
     return gapRect;
@@ -2841,15 +2855,13 @@ int RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, int position
             // The border can potentially be further extended by our containingBlock().
             return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
         return logicalLeft;
-    }
-    else {
+    } else {
         RenderBlock* cb = this;
         while (cb != rootBlock) {
             logicalLeft += cb->logicalLeft();
             cb = cb->containingBlock();
         }
     }
-    
     return logicalLeft;
 }
 
@@ -2861,8 +2873,7 @@ int RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, int positio
             // The border can potentially be further extended by our containingBlock().
             return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
         return logicalRight;
-    }
-    else {
+    } else {
         RenderBlock* cb = this;
         while (cb != rootBlock) {
             logicalRight += cb->logicalLeft();
@@ -4296,18 +4307,8 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint&
             firstRootBoxWithChildren = root;
         lastRootBoxWithChildren = root;
 
-        // set the bottom based on whether there is a next root box
-        // FIXME: This will consider nextRootBox even if it has no children, and maybe it shouldn't.
-        int bottom;
-        if (root->nextRootBox()) {
-            // FIXME: We would prefer to make the break point halfway between the bottom
-            // of the previous root box and the top of the next root box.
-            bottom = root->nextRootBox()->lineTop();
-        } else
-            bottom = root->lineBottom() + verticalLineClickFudgeFactor;
-
         // check if this root line box is located at this y coordinate
-        if (pointInContents.y() < bottom) {
+        if (pointInContents.y() < root->selectionBottom()) {
             closestBox = root->closestLeafChildForXPos(pointInContents.x());
             if (closestBox)
                 break;
@@ -4322,7 +4323,7 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint&
     }
 
     if (closestBox) {
-        if (moveCaretToBoundary && pointInContents.y() < firstRootBoxWithChildren->lineTop() - verticalLineClickFudgeFactor) {
+        if (moveCaretToBoundary && pointInContents.y() < firstRootBoxWithChildren->selectionTop()) {
             // y coordinate is above first root line box, so return the start of the first
             return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
         }
index 9370f49..1cc89c0 100644 (file)
@@ -115,14 +115,13 @@ public:
     bool containsNonZeroBidiLevel() const;
 
     GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer);
-    IntRect fillLogicalLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, 
-                                        int blockX, int blockY, int tx, int ty, const PaintInfo*);
-    IntRect fillLogicalRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
-                                         int blockX, int blockY, int tx, int ty, const PaintInfo*);
-    IntRect fillLineSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo*);
-
+    IntRect logicalLeftSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                    RenderObject* selObj, int logicalLeft, int logicalTop, int logicalHeight, const PaintInfo*);
+    IntRect logicalRightSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                                     RenderObject* selObj, int logicalRight, int logicalTop, int logicalHeight, const PaintInfo*);
     void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
-
+    IntRect logicalRectToPhysicalRect(const IntPoint& physicalPosition, const IntRect& logicalRect);
+        
     // Helper methods for computing line counts and heights for line counts.
     RootInlineBox* lineAtIndex(int);
     int lineCount();
@@ -531,17 +530,17 @@ private:
     }
     virtual bool shouldPaintSelectionGaps() const;
     bool isSelectionRoot() const;
-    GapRects fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
-                               int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* = 0);
-    GapRects fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
-                                     int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
-    GapRects fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
-                                    int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
-    IntRect fillBlockSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
-                                  int blockX, int blockY, const PaintInfo*);
+    GapRects selectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                           int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* = 0);
+    GapRects inlineSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                           int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo*);
+    GapRects blockSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                           int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo*);
+    IntRect blockSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
+                              int lastLogicalTop, int lastLogicalLeft, int lastLogicalRight, int logicalBottom, const PaintInfo*);
     int logicalLeftSelectionOffset(RenderBlock* rootBlock, int position);
     int logicalRightSelectionOffset(RenderBlock* rootBlock, int position);
-
+    
     virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
     virtual void absoluteQuads(Vector<FloatQuad>&);
 
index 625a643..dd2a7be 100644 (file)
@@ -3235,7 +3235,14 @@ IntPoint RenderBox::flipForWritingMode(const IntPoint& position)
 {
     if (!style()->isFlippedBlocksWritingMode())
         return position;
-    return style()->isHorizontalWritingMode() ? IntPoint(position.x(), logicalHeight() - position.y()) : IntPoint(logicalHeight() - position.x(), position.y());
+    return style()->isHorizontalWritingMode() ? IntPoint(position.x(), height() - position.y()) : IntPoint(width() - position.x(), position.y());
+}
+
+IntSize RenderBox::flipForWritingMode(const IntSize& offset)
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return offset;
+    return style()->isHorizontalWritingMode() ? IntSize(offset.width(), height() - offset.height()) : IntSize(width() - offset.width(), offset.height());
 }
 
 IntSize RenderBox::locationOffsetIncludingFlipping()
index f1b57a2..44d84ba 100644 (file)
@@ -53,6 +53,7 @@ public:
     int logicalLeft() const { return style()->isHorizontalWritingMode() ? x() : y(); }
     int logicalRight() const { return logicalLeft() + logicalWidth(); }
     int logicalTop() const { return style()->isHorizontalWritingMode() ? y() : x(); }
+    int logicalBottom() const { return logicalTop() + logicalHeight(); }
     int logicalWidth() const { return style()->isHorizontalWritingMode() ? width() : height(); }
     int logicalHeight() const { return style()->isHorizontalWritingMode() ? height() : width(); }
 
@@ -383,6 +384,7 @@ public:
     IntPoint flipForWritingMode(RenderBox* child, const IntPoint&, FlippingAdjustment);
     int flipForWritingMode(int position);
     IntPoint flipForWritingMode(const IntPoint&);
+    IntSize flipForWritingMode(const IntSize&);
     void flipForWritingMode(IntRect&);
     IntSize locationOffsetIncludingFlipping();
 
index 8cbbbbb..3e5b6c7 100644 (file)
@@ -238,7 +238,8 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn
     int maxHeight = maxAscent + maxDescent;
     int lineTop = heightOfBlock;
     int lineBottom = heightOfBlock;
-    placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom);
+    bool setLineTop = false;
+    placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop);
     computeBlockDirectionOverflow(lineTop, lineBottom, noQuirksMode, textBoxDataMap);
     setLineTopBottomPositions(lineTop, lineBottom);
 
@@ -249,7 +250,8 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn
     return heightOfBlock + maxHeight;
 }
 
-GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const PaintInfo* paintInfo)
+GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 
+                                         int selTop, int selHeight, const PaintInfo* paintInfo)
 {
     RenderObject::SelectionState lineState = selectionState();
 
@@ -261,13 +263,11 @@ GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBl
     InlineBox* firstBox = firstSelectedBox();
     InlineBox* lastBox = lastSelectedBox();
     if (leftGap)
-        result.uniteLeft(block()->fillLogicalLeftSelectionGap(firstBox->parent()->renderer(),
-                                                              firstBox->x(), selTop, selHeight,
-                                                              rootBlock, blockX, blockY, tx, ty, paintInfo));
+        result.uniteLeft(block()->logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+                                                          firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, paintInfo));
     if (rightGap)
-        result.uniteRight(block()->fillLogicalRightSelectionGap(lastBox->parent()->renderer(),
-                                                                lastBox->x() + lastBox->logicalWidth(), selTop, selHeight,
-                                                                rootBlock, blockX, blockY, tx, ty, paintInfo));
+        result.uniteRight(block()->logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+                                                            lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, paintInfo));
 
     // When dealing with bidi text, a non-contiguous selection region is possible.
     // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out
@@ -278,15 +278,20 @@ GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBl
     // We can see that the |bbb| run is not part of the selection while the runs around it are.
     if (firstBox && firstBox != lastBox) {
         // Now fill in any gaps on the line that occurred between two selected elements.
-        int lastX = firstBox->x() + firstBox->logicalWidth();
+        int lastLogicalLeft = firstBox->logicalRight();
         bool isPreviousBoxSelected = firstBox->selectionState() != RenderObject::SelectionNone;
         for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
             if (box->selectionState() != RenderObject::SelectionNone) {
-                if (isPreviousBoxSelected)  // VisibleSelection may be non-contiguous, see comment above.
-                    result.uniteCenter(block()->fillLineSelectionGap(box->parent()->renderer(),
-                                                                     lastX + tx, selTop + ty,
-                                                                     box->x() - lastX, selHeight, paintInfo));
-                lastX = box->x() + box->logicalWidth();
+                IntRect logicalRect(lastLogicalLeft, selTop, box->logicalLeft() - lastLogicalLeft, selHeight);
+                logicalRect.move(renderer()->style()->isHorizontalWritingMode() ? offsetFromRootBlock : IntSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
+                IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
+                if (isPreviousBoxSelected && gapRect.width() > 0 && gapRect.height() > 0) {
+                    if (paintInfo && box->parent()->renderer()->style()->visibility() == VISIBLE)
+                        paintInfo->context->fillRect(gapRect, box->parent()->renderer()->selectionBackgroundColor(), box->parent()->renderer()->style()->colorSpace());
+                    // VisibleSelection may be non-contiguous, see comment above.
+                    result.uniteCenter(gapRect);
+                }
+                lastLogicalLeft = box->logicalRight();
             }
             if (box == lastBox)
                 break;
@@ -347,18 +352,18 @@ InlineBox* RootInlineBox::lastSelectedBox()
 int RootInlineBox::selectionTop() const
 {
     int selectionTop = m_lineTop;
-    if (!prevRootBox())
+    if (renderer()->style()->isFlippedLinesWritingMode())
         return selectionTop;
 
-    int prevBottom = prevRootBox()->selectionBottom();
+    int prevBottom = prevRootBox() ? prevRootBox()->selectionBottom() : block()->borderBefore() + block()->paddingBefore();
     if (prevBottom < selectionTop && block()->containsFloats()) {
         // This line has actually been moved further down, probably from a large line-height, but possibly because the
         // line was forced to clear floats.  If so, let's check the offsets, and only be willing to use the previous
-        // line's bottom overflow if the offsets are greater on both sides.
-        int prevLeft = block()->logicalLeftOffsetForLine(prevBottom, !prevRootBox());
-        int prevRight = block()->logicalRightOffsetForLine(prevBottom, !prevRootBox());
-        int newLeft = block()->logicalLeftOffsetForLine(selectionTop, !prevRootBox());
-        int newRight = block()->logicalRightOffsetForLine(selectionTop, !prevRootBox());
+        // line's bottom if the offsets are greater on both sides.
+        int prevLeft = block()->logicalLeftOffsetForLine(prevBottom, false);
+        int prevRight = block()->logicalRightOffsetForLine(prevBottom, false);
+        int newLeft = block()->logicalLeftOffsetForLine(selectionTop, false);
+        int newRight = block()->logicalRightOffsetForLine(selectionTop, false);
         if (prevLeft > newLeft || prevRight < newRight)
             return selectionTop;
     }
@@ -366,6 +371,28 @@ int RootInlineBox::selectionTop() const
     return prevBottom;
 }
 
+int RootInlineBox::selectionBottom() const
+{
+    int selectionBottom = m_lineBottom;
+    if (!renderer()->style()->isFlippedLinesWritingMode() || !nextRootBox())
+        return selectionBottom;
+
+    int nextTop = nextRootBox()->selectionTop();
+    if (nextTop > selectionBottom && block()->containsFloats()) {
+        // The next line has actually been moved further over, probably from a large line-height, but possibly because the
+        // line was forced to clear floats.  If so, let's check the offsets, and only be willing to use the next
+        // line's top if the offsets are greater on both sides.
+        int nextLeft = block()->logicalLeftOffsetForLine(nextTop, false);
+        int nextRight = block()->logicalRightOffsetForLine(nextTop, false);
+        int newLeft = block()->logicalLeftOffsetForLine(selectionBottom, false);
+        int newRight = block()->logicalRightOffsetForLine(selectionBottom, false);
+        if (nextLeft > newLeft || nextRight < newRight)
+            return selectionBottom;
+    }
+
+    return nextTop;
+}
+
 RenderBlock* RootInlineBox::block() const
 {
     return toRenderBlock(renderer());
index 9c09b82..f13d00f 100644 (file)
@@ -54,7 +54,7 @@ public:
     void setPaginationStrut(int s) { m_paginationStrut = s; }
 
     int selectionTop() const;
-    int selectionBottom() const { return lineBottom(); }
+    int selectionBottom() const;
     int selectionHeight() const { return max(0, selectionBottom() - selectionTop()); }
 
     int alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAndFallbackFontsMap&);
@@ -106,8 +106,7 @@ public:
     InlineBox* firstSelectedBox();
     InlineBox* lastSelectedBox();
 
-    GapRects fillLineSelectionGap(int selTop, int selHeight, RenderBlock* rootBlock, int blockX, int blockY,
-                                  int tx, int ty, const PaintInfo*);
+    GapRects lineSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, int selTop, int selHeight, const PaintInfo*);
 
     RenderBlock* block() const;