[webkit-reviews] review denied: [Bug 24168] RTL: Home/End key does not behave correctly in mixed bidi text in RTL document : [Attachment 29402] patch w/ Layout test

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Tue Apr 21 20:02:47 PDT 2009


mitz at webkit.org has denied Xiaomei Ji <xji at chromium.org>'s request for review:
Bug 24168: RTL: Home/End key does not behave correctly in mixed bidi text in
RTL document
https://bugs.webkit.org/show_bug.cgi?id=24168

Attachment 29402: patch w/ Layout test
https://bugs.webkit.org/attachment.cgi?id=29402&action=review

------- Additional Comments from mitz at webkit.org
I think you are right: you should change the backward/forward, not the
left/right variant, and make the home/end keys map to back/forward.

Please use "logical" instead of the abbreviation "logic".

A typical line contains very few leaf boxes (typically 1, perhaps 2 for
contenteditable text with line-break: after-white-space, but hardly ever more
than 10), so reconstructing the logical order every time for an operation like
home/end is not a problem. Adding two pointer-sized members to InlineBox is not
necessary, and has a severe impact on memory use.

I think it would actually be simpler to use a Vector<InlineBox*>, fill it up
with the boxes in visual order (i.e. in nextLeafChild() order), then do the
reordering in-place in the vector.

You could have one

static void getLeafBoxesInLogicalOrder(RootInlineBox*, Vector<InlineBox*>&)

that did that. You wouldn't even need a helper function for reversing because
you could use std::reverse().

+    unsigned char levelLow = 128;
+    unsigned char levelHigh = 0;

I know that the names levelLow and levelHigh are used in BidiResolver, but
those are old and rather unusual names. minLevel and maxLevel would be better.

+    InlineBox* firstBox = NULL;
+    InlineBox* lastBox = NULL;

This will go away if you use a Vector-based getLeafBoxesInLogicalOrder(), but I
just wanted to point out that WebKit style is to use 0, not NULL, for the null
pointer, and that since you follow with a call to reconstructLogicOrder(),
which initializes firstBox and lastBox, you do not need to initialize them when
defining them anyway.

+    while (1) {
+	 if (!startBox)
+	     return;

Since there is nothing after the while loop, this can be written simply as
+    while (startBox)

+	 RenderObject *startRenderer = startBox->renderer();

The star should go next to RenderObject.

+	 if (!startRenderer) {
+	     startNode = NULL;
+	     return;
+	 }

Can this ever happen? I know that there is other old code checking for this,
but I don't think this case can happen. Maybe the code should assert that it
doesn't happen. Again, if you leave this code in, please use 0 instead of NULL.


+    RootInlineBox *rootBox = rootBoxForLine(c);

The start should go next to the type name.

+    // Generated content (e.g. list markers and CSS :before and :after
+    // pseudoelements) have no corresponding DOM element, and so cannot be
+    // represented by a VisiblePosition.  Use whatever follows instead.

I don't understand this comment. Where is the part where you "use whatever
follows"? I think it is actually part of getLogicStartBoxAndNode() now!

+    InlineBox *logicStartBox = NULL;
+    Node *logicStartNode = NULL;

I think the rule should be that getLogicStartBoxAndNode() initializes those.
Also, please correct the placement of the stars.

+    if (logicStartBox == NULL || logicStartNode == NULL) {
+	 return VisiblePosition();
+    }

The WebKit style of writing this is
+    if (!logicStartBox || !logicStartNode)
+	 return VisiblePosition();

without NULL or 0 and without braces around the single-line clause. Also,
shouldn't it be enough to only null-test the node?

+    int startOffset = 0;
+    if (logicStartBox->isInlineTextBox()) {
+	 InlineTextBox *startTextBox = static_cast<InlineTextBox
*>(logicStartBox);
+	 startOffset = startTextBox->start();
+    }

I think you can use InlineBox::caretMinOffset() here instead of special-casing
InlineTextBox.

+VisiblePosition logicStartOfLine(const VisiblePosition& c)
+{
+    VisiblePosition visPos = logicStartPositionForLine(c);
+    
+    if (visPos.isNotNull()) {

You can change this to an early return.

+    int endOffset = 1;
+    if (logicEndNode->hasTagName(brTag)) {
+	 endOffset = 0;
+    } else if (logicEndBox->isInlineTextBox()) {
+	 InlineTextBox *endTextBox = static_cast<InlineTextBox *>(logicEndBox);

+	 endOffset = endTextBox->start();
+	 if (!endTextBox->isLineBreak())
+	     endOffset += endTextBox->len();
+    }

And here you can use InlineBox::caretMaxOffset() in the else clause, instead of
special-casing InlineTextBox. Can you use caretMaxOffset() to get the desired
result for a <br> too?

+bool inSameLogicLine(const VisiblePosition &a, const VisiblePosition &b)

Can inSameLogicLine(a, b) and inSameLine(a, b) ever return a different result?

Finally, I want to ask about thse two cases:

+	 // Make sure the start of line is not greater than the given input
position.  Else use the previous position to 
+	 // obtain start of line.  This condition happens when the input
position is before the space character at the end 
+	 // of a soft-wrapped non-editable line. In this scenario,
logicStartPositionForLine would incorrectly hand back a position
+	 // greater than the input position.  This fix is to account for the
discrepancy between lines with webkit-line-break:after-white-space 
+	 // style versus lines without that style, which would break before a
space by default. 
+	 Position p = visPos.deepEquivalent();
+	 if (p.m_offset > c.deepEquivalent().m_offset &&
p.node()->isSameNode(c.deepEquivalent().node())) {

and

+    // Make sure the end of line is at the same line as the given input
position.  Else use the previous position to 
+    // obtain end of line.  This condition happens when the input position is
before the space character at the end 
+    // of a soft-wrapped non-editable line. In this scenario,
logicEndPositionForLine would incorrectly hand back a position
+    // in the next line instead. This fix is to account for the discrepancy
between lines with webkit-line-break:after-white-space style
+    // versus lines without that style, which would break before a space by
default. 
+    if (!inSameLogicLine(c, visPos)) {

I don't fully understand the former and I am not sure the latter can happen.
Are they covered by your test? Do we need them?

+//	       positions.push({ node: sel.anchorNode, offset:
sel.anchorOffset});

+ //	       positions.push({ node: sel.anchorNode, offset:
sel.anchorOffset});

Please remove commented-out code from the test.

Property changes on: LayoutTests/editing/selection/home-end.html
___________________________________________________________________
Name: svn:executable
   + *

This is unnecessary.

Looks like you are in the right direction, but you can do the same with simpler
code!


More information about the webkit-reviews mailing list