Changeset 157349 in webkit
- Timestamp:
- Oct 12, 2013, 3:33:53 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
-
ChangeLog (modified) (1 diff)
-
rendering/RenderObject.cpp (modified) (4 diffs)
-
rendering/RenderObject.h (modified) (1 diff)
-
rendering/RenderText.cpp (modified) (1 diff)
-
rendering/RenderTextLineBoxes.cpp (modified) (4 diffs)
-
rendering/RenderTextLineBoxes.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r157348 r157349 1 2013-10-12 Antti Koivisto <antti@apple.com> 2 3 Move positionForPoint to RenderTextLineBoxes 4 https://bugs.webkit.org/show_bug.cgi?id=122703 5 6 Reviewed by Andreas Kling. 7 1 8 2013-10-12 Andreas Kling <akling@apple.com> 2 9 -
trunk/Source/WebCore/rendering/RenderObject.cpp
r157222 r157349 2498 2498 } 2499 2499 2500 VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity) 2500 VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity) const 2501 2501 { 2502 2502 // If this is a non-anonymous renderer in an editable area, then it's simple. … … 2522 2522 2523 2523 // Find a nearby non-anonymous renderer. 2524 RenderObject* child = this;2525 while ( RenderObject* parent = child->parent()) {2524 const RenderObject* child = this; 2525 while (const RenderElement* parent = child->parent()) { 2526 2526 // Find non-anonymous content after. 2527 RenderObject* renderer = child;2527 const RenderObject* renderer = child; 2528 2528 while ((renderer = renderer->nextInPreOrder(parent))) { 2529 2529 if (Node* node = renderer->nonPseudoNode()) … … 2541 2541 2542 2542 // Use the parent itself unless it too is anonymous. 2543 if ( Node* node = parent->nonPseudoNode())2544 return VisiblePosition(firstPositionInOrBeforeNode( node), DOWNSTREAM);2543 if (Element* element = parent->nonPseudoElement()) 2544 return VisiblePosition(firstPositionInOrBeforeNode(element), DOWNSTREAM); 2545 2545 2546 2546 // Repeat at the next level up. … … 2552 2552 } 2553 2553 2554 VisiblePosition RenderObject::createVisiblePosition(const Position& position) 2554 VisiblePosition RenderObject::createVisiblePosition(const Position& position) const 2555 2555 { 2556 2556 if (position.isNotNull()) -
trunk/Source/WebCore/rendering/RenderObject.h
r157222 r157349 670 670 671 671 virtual VisiblePosition positionForPoint(const LayoutPoint&); 672 VisiblePosition createVisiblePosition(int offset, EAffinity) ;673 VisiblePosition createVisiblePosition(const Position&) ;672 VisiblePosition createVisiblePosition(int offset, EAffinity) const; 673 VisiblePosition createVisiblePosition(const Position&) const; 674 674 675 675 // returns the containing block level element for this element. -
trunk/Source/WebCore/rendering/RenderText.cpp
r157346 r157349 404 404 } 405 405 406 enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPositionIsNotAtStart };407 408 static bool lineDirectionPointFitsInBox(int pointLineDirection, InlineTextBox* box, ShouldAffinityBeDownstream& shouldAffinityBeDownstream)409 {410 shouldAffinityBeDownstream = AlwaysDownstream;411 412 // the x coordinate is equal to the left edge of this box413 // the affinity must be downstream so the position doesn't jump back to the previous line414 // except when box is the first box in the line415 if (pointLineDirection <= box->logicalLeft()) {416 shouldAffinityBeDownstream = !box->prevLeafChild() ? UpstreamIfPositionIsNotAtStart : AlwaysDownstream;417 return true;418 }419 420 // and the x coordinate is to the left of the right edge of this box421 // check to see if position goes in this box422 if (pointLineDirection < box->logicalRight()) {423 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;424 return true;425 }426 427 // box is first on line428 // and the x coordinate is to the left of the first text box left edge429 if (!box->prevLeafChildIgnoringLineBreak() && pointLineDirection < box->logicalLeft())430 return true;431 432 if (!box->nextLeafChildIgnoringLineBreak()) {433 // box is last on line434 // and the x coordinate is to the right of the last text box right edge435 // generate VisiblePosition, use UPSTREAM affinity if possible436 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;437 return true;438 }439 440 return false;441 }442 443 static VisiblePosition createVisiblePositionForBox(const InlineBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)444 {445 EAffinity affinity = VP_DEFAULT_AFFINITY;446 switch (shouldAffinityBeDownstream) {447 case AlwaysDownstream:448 affinity = DOWNSTREAM;449 break;450 case AlwaysUpstream:451 affinity = VP_UPSTREAM_IF_POSSIBLE;452 break;453 case UpstreamIfPositionIsNotAtStart:454 affinity = offset > box->caretMinOffset() ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;455 break;456 }457 return box->renderer().createVisiblePosition(offset, affinity);458 }459 460 static VisiblePosition createVisiblePositionAfterAdjustingOffsetForBiDi(const InlineTextBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)461 {462 ASSERT(box);463 ASSERT(offset >= 0);464 465 if (offset && static_cast<unsigned>(offset) < box->len())466 return createVisiblePositionForBox(box, box->start() + offset, shouldAffinityBeDownstream);467 468 bool positionIsAtStartOfBox = !offset;469 if (positionIsAtStartOfBox == box->isLeftToRightDirection()) {470 // offset is on the left edge471 472 const InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();473 if ((prevBox && prevBox->bidiLevel() == box->bidiLevel())474 || box->renderer().containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA475 return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);476 477 if (prevBox && prevBox->bidiLevel() > box->bidiLevel()) {478 // e.g. left of B in aDC12BAb479 const InlineBox* leftmostBox;480 do {481 leftmostBox = prevBox;482 prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();483 } while (prevBox && prevBox->bidiLevel() > box->bidiLevel());484 return createVisiblePositionForBox(leftmostBox, leftmostBox->caretRightmostOffset(), shouldAffinityBeDownstream);485 }486 487 if (!prevBox || prevBox->bidiLevel() < box->bidiLevel()) {488 // e.g. left of D in aDC12BAb489 const InlineBox* rightmostBox;490 const InlineBox* nextBox = box;491 do {492 rightmostBox = nextBox;493 nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();494 } while (nextBox && nextBox->bidiLevel() >= box->bidiLevel());495 return createVisiblePositionForBox(rightmostBox,496 box->isLeftToRightDirection() ? rightmostBox->caretMaxOffset() : rightmostBox->caretMinOffset(), shouldAffinityBeDownstream);497 }498 499 return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);500 }501 502 const InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();503 if ((nextBox && nextBox->bidiLevel() == box->bidiLevel())504 || box->renderer().containingBlock()->style()->direction() == box->direction())505 return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);506 507 // offset is on the right edge508 if (nextBox && nextBox->bidiLevel() > box->bidiLevel()) {509 // e.g. right of C in aDC12BAb510 const InlineBox* rightmostBox;511 do {512 rightmostBox = nextBox;513 nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();514 } while (nextBox && nextBox->bidiLevel() > box->bidiLevel());515 return createVisiblePositionForBox(rightmostBox, rightmostBox->caretLeftmostOffset(), shouldAffinityBeDownstream);516 }517 518 if (!nextBox || nextBox->bidiLevel() < box->bidiLevel()) {519 // e.g. right of A in aDC12BAb520 const InlineBox* leftmostBox;521 const InlineBox* prevBox = box;522 do {523 leftmostBox = prevBox;524 prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();525 } while (prevBox && prevBox->bidiLevel() >= box->bidiLevel());526 return createVisiblePositionForBox(leftmostBox,527 box->isLeftToRightDirection() ? leftmostBox->caretMinOffset() : leftmostBox->caretMaxOffset(), shouldAffinityBeDownstream);528 }529 530 return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);531 }532 533 406 VisiblePosition RenderText::positionForPoint(const LayoutPoint& point) 534 407 { 535 if (!firstTextBox() || textLength() == 0) 536 return createVisiblePosition(0, DOWNSTREAM); 537 538 LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() : point.y(); 539 LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x(); 540 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); 541 542 InlineTextBox* lastBox = 0; 543 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { 544 if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak()) 545 box = box->nextTextBox(); 546 547 const RootInlineBox& rootBox = box->root(); 548 LayoutUnit top = min(rootBox.selectionTop(), rootBox.lineTop()); 549 if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) { 550 LayoutUnit bottom = rootBox.selectionBottom(); 551 if (rootBox.nextRootBox()) 552 bottom = min(bottom, rootBox.nextRootBox()->lineTop()); 553 554 if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) { 555 ShouldAffinityBeDownstream shouldAffinityBeDownstream; 556 if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldAffinityBeDownstream)) 557 return createVisiblePositionAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream); 558 } 559 } 560 lastBox = box; 561 } 562 563 if (lastBox) { 564 ShouldAffinityBeDownstream shouldAffinityBeDownstream; 565 lineDirectionPointFitsInBox(pointLineDirection, lastBox, shouldAffinityBeDownstream); 566 return createVisiblePositionAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream); 567 } 568 return createVisiblePosition(0, DOWNSTREAM); 408 return m_lineBoxes.positionForPoint(*this, point); 569 409 } 570 410 -
trunk/Source/WebCore/rendering/RenderTextLineBoxes.cpp
r157346 r157349 28 28 29 29 #include "InlineTextBox.h" 30 #include "RenderBlock.h" 30 31 #include "RenderStyle.h" 31 32 #include "RootInlineBox.h" … … 223 224 maxOffset = std::max<int>(maxOffset, box->start() + box->len()); 224 225 return maxOffset; 226 } 227 228 enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPositionIsNotAtStart }; 229 230 static bool lineDirectionPointFitsInBox(int pointLineDirection, const InlineTextBox& box, ShouldAffinityBeDownstream& shouldAffinityBeDownstream) 231 { 232 shouldAffinityBeDownstream = AlwaysDownstream; 233 234 // the x coordinate is equal to the left edge of this box 235 // the affinity must be downstream so the position doesn't jump back to the previous line 236 // except when box is the first box in the line 237 if (pointLineDirection <= box.logicalLeft()) { 238 shouldAffinityBeDownstream = !box.prevLeafChild() ? UpstreamIfPositionIsNotAtStart : AlwaysDownstream; 239 return true; 240 } 241 242 // and the x coordinate is to the left of the right edge of this box 243 // check to see if position goes in this box 244 if (pointLineDirection < box.logicalRight()) { 245 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; 246 return true; 247 } 248 249 // box is first on line 250 // and the x coordinate is to the left of the first text box left edge 251 if (!box.prevLeafChildIgnoringLineBreak() && pointLineDirection < box.logicalLeft()) 252 return true; 253 254 if (!box.nextLeafChildIgnoringLineBreak()) { 255 // box is last on line 256 // and the x coordinate is to the right of the last text box right edge 257 // generate VisiblePosition, use UPSTREAM affinity if possible 258 shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart; 259 return true; 260 } 261 262 return false; 263 } 264 265 static VisiblePosition createVisiblePositionForBox(const InlineBox& box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream) 266 { 267 EAffinity affinity = VP_DEFAULT_AFFINITY; 268 switch (shouldAffinityBeDownstream) { 269 case AlwaysDownstream: 270 affinity = DOWNSTREAM; 271 break; 272 case AlwaysUpstream: 273 affinity = VP_UPSTREAM_IF_POSSIBLE; 274 break; 275 case UpstreamIfPositionIsNotAtStart: 276 affinity = offset > box.caretMinOffset() ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM; 277 break; 278 } 279 return box.renderer().createVisiblePosition(offset, affinity); 280 } 281 282 static VisiblePosition createVisiblePositionAfterAdjustingOffsetForBiDi(const InlineTextBox& box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream) 283 { 284 ASSERT(offset >= 0); 285 286 if (offset && static_cast<unsigned>(offset) < box.len()) 287 return createVisiblePositionForBox(box, box.start() + offset, shouldAffinityBeDownstream); 288 289 bool positionIsAtStartOfBox = !offset; 290 if (positionIsAtStartOfBox == box.isLeftToRightDirection()) { 291 // offset is on the left edge 292 293 const InlineBox* prevBox = box.prevLeafChildIgnoringLineBreak(); 294 if ((prevBox && prevBox->bidiLevel() == box.bidiLevel()) 295 || box.renderer().containingBlock()->style()->direction() == box.direction()) // FIXME: left on 12CBA 296 return createVisiblePositionForBox(box, box.caretLeftmostOffset(), shouldAffinityBeDownstream); 297 298 if (prevBox && prevBox->bidiLevel() > box.bidiLevel()) { 299 // e.g. left of B in aDC12BAb 300 const InlineBox* leftmostBox; 301 do { 302 leftmostBox = prevBox; 303 prevBox = leftmostBox->prevLeafChildIgnoringLineBreak(); 304 } while (prevBox && prevBox->bidiLevel() > box.bidiLevel()); 305 return createVisiblePositionForBox(*leftmostBox, leftmostBox->caretRightmostOffset(), shouldAffinityBeDownstream); 306 } 307 308 if (!prevBox || prevBox->bidiLevel() < box.bidiLevel()) { 309 // e.g. left of D in aDC12BAb 310 const InlineBox* rightmostBox; 311 const InlineBox* nextBox = &box; 312 do { 313 rightmostBox = nextBox; 314 nextBox = rightmostBox->nextLeafChildIgnoringLineBreak(); 315 } while (nextBox && nextBox->bidiLevel() >= box.bidiLevel()); 316 return createVisiblePositionForBox(*rightmostBox, 317 box.isLeftToRightDirection() ? rightmostBox->caretMaxOffset() : rightmostBox->caretMinOffset(), shouldAffinityBeDownstream); 318 } 319 320 return createVisiblePositionForBox(box, box.caretRightmostOffset(), shouldAffinityBeDownstream); 321 } 322 323 const InlineBox* nextBox = box.nextLeafChildIgnoringLineBreak(); 324 if ((nextBox && nextBox->bidiLevel() == box.bidiLevel()) 325 || box.renderer().containingBlock()->style()->direction() == box.direction()) 326 return createVisiblePositionForBox(box, box.caretRightmostOffset(), shouldAffinityBeDownstream); 327 328 // offset is on the right edge 329 if (nextBox && nextBox->bidiLevel() > box.bidiLevel()) { 330 // e.g. right of C in aDC12BAb 331 const InlineBox* rightmostBox; 332 do { 333 rightmostBox = nextBox; 334 nextBox = rightmostBox->nextLeafChildIgnoringLineBreak(); 335 } while (nextBox && nextBox->bidiLevel() > box.bidiLevel()); 336 return createVisiblePositionForBox(*rightmostBox, rightmostBox->caretLeftmostOffset(), shouldAffinityBeDownstream); 337 } 338 339 if (!nextBox || nextBox->bidiLevel() < box.bidiLevel()) { 340 // e.g. right of A in aDC12BAb 341 const InlineBox* leftmostBox; 342 const InlineBox* prevBox = &box; 343 do { 344 leftmostBox = prevBox; 345 prevBox = leftmostBox->prevLeafChildIgnoringLineBreak(); 346 } while (prevBox && prevBox->bidiLevel() >= box.bidiLevel()); 347 return createVisiblePositionForBox(*leftmostBox, 348 box.isLeftToRightDirection() ? leftmostBox->caretMinOffset() : leftmostBox->caretMaxOffset(), shouldAffinityBeDownstream); 349 } 350 351 return createVisiblePositionForBox(box, box.caretLeftmostOffset(), shouldAffinityBeDownstream); 352 } 353 354 VisiblePosition RenderTextLineBoxes::positionForPoint(const RenderText& renderer, const LayoutPoint& point) const 355 { 356 if (!m_first || !renderer.textLength()) 357 return renderer.createVisiblePosition(0, DOWNSTREAM); 358 359 LayoutUnit pointLineDirection = m_first->isHorizontal() ? point.x() : point.y(); 360 LayoutUnit pointBlockDirection = m_first->isHorizontal() ? point.y() : point.x(); 361 bool blocksAreFlipped = renderer.style()->isFlippedBlocksWritingMode(); 362 363 InlineTextBox* lastBox = nullptr; 364 for (auto box = m_first; box; box = box->nextTextBox()) { 365 if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak()) 366 box = box->nextTextBox(); 367 368 auto& rootBox = box->root(); 369 LayoutUnit top = std::min(rootBox.selectionTop(), rootBox.lineTop()); 370 if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) { 371 LayoutUnit bottom = rootBox.selectionBottom(); 372 if (rootBox.nextRootBox()) 373 bottom = std::min(bottom, rootBox.nextRootBox()->lineTop()); 374 375 if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) { 376 ShouldAffinityBeDownstream shouldAffinityBeDownstream; 377 if (lineDirectionPointFitsInBox(pointLineDirection, *box, shouldAffinityBeDownstream)) 378 return createVisiblePositionAfterAdjustingOffsetForBiDi(*box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream); 379 } 380 } 381 lastBox = box; 382 } 383 384 if (lastBox) { 385 ShouldAffinityBeDownstream shouldAffinityBeDownstream; 386 lineDirectionPointFitsInBox(pointLineDirection, *lastBox, shouldAffinityBeDownstream); 387 return createVisiblePositionAfterAdjustingOffsetForBiDi(*lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream); 388 } 389 return renderer.createVisiblePosition(0, DOWNSTREAM); 225 390 } 226 391 … … 306 471 } 307 472 473 inline void RenderTextLineBoxes::checkConsistency() const 474 { 308 475 #if !ASSERT_DISABLED 309 RenderTextLineBoxes::~RenderTextLineBoxes()310 {311 ASSERT(!m_first);312 ASSERT(!m_last);313 }314 315 void RenderTextLineBoxes::checkConsistency() const316 {317 476 #ifdef CHECK_CONSISTENCY 318 477 const InlineTextBox* prev = nullptr; … … 324 483 ASSERT(prev == m_last); 325 484 #endif 326 }327 485 #endif 328 329 } 486 } 487 488 #if !ASSERT_DISABLED 489 RenderTextLineBoxes::~RenderTextLineBoxes() 490 { 491 ASSERT(!m_first); 492 ASSERT(!m_last); 493 } 494 #endif 495 496 } -
trunk/Source/WebCore/rendering/RenderTextLineBoxes.h
r157346 r157349 28 28 29 29 #include "LayoutRect.h" 30 #include "VisiblePosition.h" 30 31 31 32 namespace WebCore { … … 57 58 int caretMaxOffset(const RenderText&) const; 58 59 60 VisiblePosition positionForPoint(const RenderText&, const LayoutPoint&) const; 61 59 62 IntRect boundingBox(const RenderText&) const; 60 63 LayoutRect visualOverflowBoundingBox(const RenderText&) const; … … 68 71 69 72 private: 70 #if !ASSERT_DISABLED71 73 void checkConsistency() const; 72 #else73 void checkConsistency() const { }74 #endif75 74 76 75 InlineTextBox* m_first; … … 80 79 } 81 80 82 83 81 #endif
Note:
See TracChangeset
for help on using the changeset viewer.