static void getLeafBoxesInLogicalOrder(RootInlineBox* rootBox, Vector<InlineBox*>& leafBoxesInLogicalOrder) { unsigned char minLevel = 128; unsigned char maxLevel = 0; unsigned count = 0; InlineBox* r = rootBox->firstLeafChild(); // First find highest and lowest levels, // and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order. while (r) { if (r->bidiLevel() > maxLevel) maxLevel = r->bidiLevel(); if (r->bidiLevel() < minLevel) minLevel = r->bidiLevel(); leafBoxesInLogicalOrder.append(r); r = r->nextLeafChild(); ++count; } if (rootBox->renderer()->style()->visuallyOrdered()) return; // Reverse of reordering of the line (L2 according to Bidi spec): // L2. From the highest level found in the text to the lowest odd level on each line, // reverse any contiguous sequence of characters that are at that level or higher. // Reversing the reordering of the line is only done up to the lowest odd level. if (!(minLevel % 2)) minLevel++; InlineBox** end = leafBoxesInLogicalOrder.end(); while (minLevel <= maxLevel) { InlineBox** iter = leafBoxesInLogicalOrder.begin(); while (iter != end) { while (iter != end) { if ((*iter)->bidiLevel() >= minLevel) break; ++iter; } InlineBox** first = iter; while (iter != end) { if ((*iter)->bidiLevel() < minLevel) break; ++iter; } InlineBox** last = iter; std::reverse(first, last); } ++minLevel; } }
RenderedPosition RenderedPosition::rightBoundaryOfBidiRun(unsigned char bidiLevelOfRun) { if (!m_inlineBox || bidiLevelOfRun > m_inlineBox->bidiLevel()) return RenderedPosition(); InlineBox* box = m_inlineBox; do { InlineBox* next = box->nextLeafChildIgnoringLineBreak(); if (!next || next->bidiLevel() < bidiLevelOfRun) return RenderedPosition(&box->layoutObject(), box, box->caretRightmostOffset()); box = next; } while (box); ASSERT_NOT_REACHED(); return RenderedPosition(); }
RenderedPosition RenderedPosition::leftBoundaryOfBidiRun(unsigned char bidiLevelOfRun) { if (!m_inlineBox || bidiLevelOfRun > m_inlineBox->bidiLevel()) return RenderedPosition(); InlineBox* box = m_inlineBox; do { InlineBox* prev = box->prevLeafChildIgnoringLineBreak(); if (!prev || prev->bidiLevel() < bidiLevelOfRun) return RenderedPosition(&box->layoutObject(), box, box->caretLeftmostOffset()); box = prev; } while (box); ASSERT_NOT_REACHED(); return RenderedPosition(); }
unsigned char RenderedPosition::bidiLevelOnRight() const { InlineBox* box = atRightmostOffsetInBox() ? nextLeafChild() : m_inlineBox; return box ? box->bidiLevel() : 0; }
Position VisiblePosition::rightVisuallyDistinctCandidate() const { Position p = m_deepPosition; if (p.isNull()) return Position(); Position downstreamStart = p.downstream(); TextDirection primaryDirection = p.primaryDirection(); while (true) { InlineBox* box; int offset; p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset); if (!box) return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); RenderObject* renderer = box->renderer(); while (true) { if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset()) return box->isLeftToRightDirection() ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); if (!renderer->node()) { box = box->nextLeafChild(); if (!box) return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); renderer = box->renderer(); offset = box->caretLeftmostOffset(); continue; } offset = box->isLeftToRightDirection() ? renderer->nextOffset(offset) : renderer->previousOffset(offset); int caretMinOffset = box->caretMinOffset(); int caretMaxOffset = box->caretMaxOffset(); if (offset > caretMinOffset && offset < caretMaxOffset) break; if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset < caretMinOffset) { // Overshot to the right. InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); if (!nextBox) { Position positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); if (positionOnRight.isNull()) return Position(); InlineBox* boxOnRight; int offsetOnRight; positionOnRight.getInlineBoxAndOffset(m_affinity, primaryDirection, boxOnRight, offsetOnRight); if (boxOnRight && boxOnRight->root() == box->root()) return Position(); return positionOnRight; } // Reposition at the other logical position corresponding to our edge's visual position and go for another round. box = nextBox; renderer = box->renderer(); offset = nextBox->caretLeftmostOffset(); continue; } ASSERT(offset == box->caretRightmostOffset()); unsigned char level = box->bidiLevel(); InlineBox* nextBox = box->nextLeafChild(); if (box->direction() == primaryDirection) { if (!nextBox) { InlineBox* logicalEnd = 0; if (primaryDirection == LTR ? box->root()->getLogicalEndBoxWithNode(logicalEnd) : box->root()->getLogicalStartBoxWithNode(logicalEnd)) { box = logicalEnd; renderer = box->renderer(); offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); } break; } if (nextBox->bidiLevel() >= level) break; level = nextBox->bidiLevel(); InlineBox* prevBox = box; do { prevBox = prevBox->prevLeafChild(); } while (prevBox && prevBox->bidiLevel() > level); if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA break; // For example, abc 123 ^ CBA or 123 ^ CBA abc box = nextBox; renderer = box->renderer(); offset = box->caretLeftmostOffset(); if (box->direction() == primaryDirection) break; continue; } while (nextBox && !nextBox->renderer()->node()) nextBox = nextBox->nextLeafChild(); if (nextBox) { box = nextBox; renderer = box->renderer(); offset = box->caretLeftmostOffset(); if (box->bidiLevel() > level) { do { nextBox = nextBox->nextLeafChild(); } while (nextBox && nextBox->bidiLevel() > level); if (!nextBox || nextBox->bidiLevel() < level) continue; } } else { // Trailing edge of a secondary run. Set to the leading edge of the entire run. while (true) { while (InlineBox* prevBox = box->prevLeafChild()) { if (prevBox->bidiLevel() < level) break; box = prevBox; } if (box->bidiLevel() == level) break; level = box->bidiLevel(); while (InlineBox* nextBox = box->nextLeafChild()) { if (nextBox->bidiLevel() < level) break; box = nextBox; } if (box->bidiLevel() == level) break; level = box->bidiLevel(); } renderer = box->renderer(); offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); } break; } p = createLegacyEditingPosition(renderer->node(), offset); if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) return p; ASSERT(p != m_deepPosition); } }
Position VisiblePosition::rightVisuallyDistinctCandidate() const { Position p = m_deepPosition; if (p.isNull()) return Position(); Position downstreamStart = mostForwardCaretPosition(p); TextDirection primaryDirection = primaryDirectionOf(*p.anchorNode()); while (true) { InlineBoxPosition boxPosition = computeInlineBoxPosition(p, m_affinity, primaryDirection); InlineBox* box = boxPosition.inlineBox; int offset = boxPosition.offsetInBox; if (!box) return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); LayoutObject* layoutObject = &box->layoutObject(); while (true) { if ((layoutObject->isReplaced() || layoutObject->isBR()) && offset == box->caretLeftmostOffset()) return box->isLeftToRightDirection() ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); if (!layoutObject->node()) { box = box->nextLeafChild(); if (!box) return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); layoutObject = &box->layoutObject(); offset = box->caretLeftmostOffset(); continue; } offset = box->isLeftToRightDirection() ? layoutObject->nextOffset(offset) : layoutObject->previousOffset(offset); int caretMinOffset = box->caretMinOffset(); int caretMaxOffset = box->caretMaxOffset(); if (offset > caretMinOffset && offset < caretMaxOffset) break; if (box->isLeftToRightDirection() ? offset > caretMaxOffset : offset < caretMinOffset) { // Overshot to the right. InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak(); if (!nextBox) { Position positionOnRight = primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition); if (positionOnRight.isNull()) return Position(); InlineBox* boxOnRight = computeInlineBoxPosition(positionOnRight, m_affinity, primaryDirection).inlineBox; if (boxOnRight && boxOnRight->root() == box->root()) return Position(); return positionOnRight; } // Reposition at the other logical position corresponding to our edge's visual position and go for another round. box = nextBox; layoutObject = &box->layoutObject(); offset = nextBox->caretLeftmostOffset(); continue; } ASSERT(offset == box->caretRightmostOffset()); unsigned char level = box->bidiLevel(); InlineBox* nextBox = box->nextLeafChild(); if (box->direction() == primaryDirection) { if (!nextBox) { InlineBox* logicalEnd = 0; if (primaryDirection == LTR ? box->root().getLogicalEndBoxWithNode(logicalEnd) : box->root().getLogicalStartBoxWithNode(logicalEnd)) { box = logicalEnd; layoutObject = &box->layoutObject(); offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); } break; } if (nextBox->bidiLevel() >= level) break; level = nextBox->bidiLevel(); InlineBox* prevBox = box; do { prevBox = prevBox->prevLeafChild(); } while (prevBox && prevBox->bidiLevel() > level); if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA break; // For example, abc 123 ^ CBA or 123 ^ CBA abc box = nextBox; layoutObject = &box->layoutObject(); offset = box->caretLeftmostOffset(); if (box->direction() == primaryDirection) break; continue; } while (nextBox && !nextBox->layoutObject().node()) nextBox = nextBox->nextLeafChild(); if (nextBox) { box = nextBox; layoutObject = &box->layoutObject(); offset = box->caretLeftmostOffset(); if (box->bidiLevel() > level) { do { nextBox = nextBox->nextLeafChild(); } while (nextBox && nextBox->bidiLevel() > level); if (!nextBox || nextBox->bidiLevel() < level) continue; } } else { // Trailing edge of a secondary run. Set to the leading edge of the entire run. while (true) { while (InlineBox* prevBox = box->prevLeafChild()) { if (prevBox->bidiLevel() < level) break; box = prevBox; } if (box->bidiLevel() == level) break; level = box->bidiLevel(); while (InlineBox* nextBox = box->nextLeafChild()) { if (nextBox->bidiLevel() < level) break; box = nextBox; } if (box->bidiLevel() == level) break; level = box->bidiLevel(); } layoutObject = &box->layoutObject(); offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); } break; } p = Position::editingPositionOf(layoutObject->node(), offset); if ((isVisuallyEquivalentCandidate(p) && mostForwardCaretPosition(p) != downstreamStart) || p.atStartOfTree() || p.atEndOfTree()) return p; ASSERT(p != m_deepPosition); } }