 Chromium Code Reviews
 Chromium Code Reviews Issue 2926823002:
  Introduce LocalCaretRect for refactoring Local{Caret,Selection}RectPosition()  (Closed)
    
  
    Issue 2926823002:
  Introduce LocalCaretRect for refactoring Local{Caret,Selection}RectPosition()  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 
| 3 * reserved. | 3 * reserved. | 
| 4 * | 4 * | 
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without | 
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions | 
| 7 * are met: | 7 * are met: | 
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright | 
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. | 
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright | 
| (...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1256 primary_direction); | 1256 primary_direction); | 
| 1257 } | 1257 } | 
| 1258 | 1258 | 
| 1259 InlineBoxPosition ComputeInlineBoxPosition(const PositionInFlatTree& position, | 1259 InlineBoxPosition ComputeInlineBoxPosition(const PositionInFlatTree& position, | 
| 1260 TextAffinity affinity, | 1260 TextAffinity affinity, | 
| 1261 TextDirection primary_direction) { | 1261 TextDirection primary_direction) { | 
| 1262 return ComputeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>( | 1262 return ComputeInlineBoxPositionTemplate<EditingInFlatTreeStrategy>( | 
| 1263 position, affinity, primary_direction); | 1263 position, affinity, primary_direction); | 
| 1264 } | 1264 } | 
| 1265 | 1265 | 
| 1266 // TODO(editing-dev): Once we mark |LayoutObject::LocalCaretRect()| |const|, | |
| 1267 // we should make this function to take |const LayoutObject&|. | |
| 1268 static LocalCaretRect ComputeLocalCaretRect( | |
| 1269 LayoutObject* layout_object, | |
| 1270 const InlineBoxPosition box_position) { | |
| 1271 return LocalCaretRect( | |
| 1272 layout_object, layout_object->LocalCaretRect(box_position.inline_box, | |
| 1273 box_position.offset_in_box)); | |
| 1274 } | |
| 1275 | |
| 1266 template <typename Strategy> | 1276 template <typename Strategy> | 
| 1267 LayoutRect LocalCaretRectOfPositionTemplate( | 1277 LocalCaretRect LocalCaretRectOfPositionTemplate( | 
| 1268 const PositionWithAffinityTemplate<Strategy>& position, | 1278 const PositionWithAffinityTemplate<Strategy>& position) { | 
| 1269 LayoutObject*& layout_object) { | 1279 if (position.IsNull()) | 
| 1270 if (position.IsNull()) { | 1280 return LocalCaretRect(); | 
| 1271 layout_object = nullptr; | 1281 Node* const node = position.AnchorNode(); | 
| 1272 return LayoutRect(); | 1282 if (!node->GetLayoutObject()) | 
| 
Xiaocheng
2017/06/08 21:00:42
We should store
LayoutObject* const layout_object
 
yosin_UTC9
2017/06/09 06:13:29
Done.
 | |
| 1273 } | 1283 return LocalCaretRect(); | 
| 1274 Node* node = position.AnchorNode(); | |
| 1275 | 1284 | 
| 1276 layout_object = node->GetLayoutObject(); | 1285 const InlineBoxPosition& box_position = | 
| 1277 if (!layout_object) | |
| 1278 return LayoutRect(); | |
| 1279 | |
| 1280 InlineBoxPosition box_position = | |
| 1281 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); | 1286 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); | 
| 1282 | 1287 | 
| 1283 if (box_position.inline_box) | 1288 if (!box_position.inline_box) | 
| 1284 layout_object = LineLayoutAPIShim::LayoutObjectFrom( | 1289 return ComputeLocalCaretRect(node->GetLayoutObject(), box_position); | 
| 
Xiaocheng
2017/06/08 21:00:41
We can use early return style without switching th
 
yosin_UTC9
2017/06/09 06:13:29
Done.
 | |
| 1285 box_position.inline_box->GetLineLayoutItem()); | |
| 1286 | 1290 | 
| 1287 return layout_object->LocalCaretRect(box_position.inline_box, | 1291 return ComputeLocalCaretRect( | 
| 1288 box_position.offset_in_box); | 1292 LineLayoutAPIShim::LayoutObjectFrom( | 
| 1293 box_position.inline_box->GetLineLayoutItem()), | |
| 1294 box_position); | |
| 1289 } | 1295 } | 
| 1290 | 1296 | 
| 1291 // This function was added because the caret rect that is calculated by | 1297 // This function was added because the caret rect that is calculated by | 
| 1292 // using the line top value instead of the selection top. | 1298 // using the line top value instead of the selection top. | 
| 1293 template <typename Strategy> | 1299 template <typename Strategy> | 
| 1294 LayoutRect LocalSelectionRectOfPositionTemplate( | 1300 LocalCaretRect LocalSelectionRectOfPositionTemplate( | 
| 1295 const PositionWithAffinityTemplate<Strategy>& position, | 1301 const PositionWithAffinityTemplate<Strategy>& position) { | 
| 1296 LayoutObject*& layout_object) { | 1302 if (position.IsNull()) | 
| 1297 if (position.IsNull()) { | 1303 return LocalCaretRect(); | 
| 1298 layout_object = nullptr; | 1304 Node* const node = position.AnchorNode(); | 
| 1299 return LayoutRect(); | 1305 if (!node->GetLayoutObject()) | 
| 1300 } | 1306 return LocalCaretRect(); | 
| 1301 Node* node = position.AnchorNode(); | |
| 1302 layout_object = node->GetLayoutObject(); | |
| 1303 if (!layout_object) | |
| 1304 return LayoutRect(); | |
| 1305 | 1307 | 
| 1306 InlineBoxPosition box_position = | 1308 const InlineBoxPosition& box_position = | 
| 1307 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); | 1309 ComputeInlineBoxPosition(position.GetPosition(), position.Affinity()); | 
| 1308 | 1310 | 
| 1309 if (!box_position.inline_box) | 1311 if (!box_position.inline_box) | 
| 1310 return LayoutRect(); | 1312 return LocalCaretRect(); | 
| 
Xiaocheng
2017/06/08 21:00:42
The original code returns a non-null LayoutObject.
 
yosin_UTC9
2017/06/09 06:13:29
I create another patch to return nullptr for layou
 | |
| 1311 | 1313 | 
| 1312 layout_object = LineLayoutAPIShim::LayoutObjectFrom( | 1314 LayoutObject* const layout_object = LineLayoutAPIShim::LayoutObjectFrom( | 
| 1313 box_position.inline_box->GetLineLayoutItem()); | 1315 box_position.inline_box->GetLineLayoutItem()); | 
| 1314 | 1316 | 
| 1315 LayoutRect rect = layout_object->LocalCaretRect(box_position.inline_box, | 1317 const LayoutRect& rect = layout_object->LocalCaretRect( | 
| 1316 box_position.offset_in_box); | 1318 box_position.inline_box, box_position.offset_in_box); | 
| 1317 | 1319 | 
| 1318 if (rect.IsEmpty()) | 1320 if (rect.IsEmpty()) | 
| 1319 return rect; | 1321 return LocalCaretRect(); | 
| 
Xiaocheng
2017/06/08 21:00:42
Ditto.
 
yosin_UTC9
2017/06/09 06:13:29
I create another patch to return nullptr for layou
 | |
| 1320 | 1322 | 
| 1321 InlineBox* const box = box_position.inline_box; | 1323 InlineBox* const box = box_position.inline_box; | 
| 1322 if (layout_object->Style()->IsHorizontalWritingMode()) { | 1324 if (layout_object->Style()->IsHorizontalWritingMode()) { | 
| 1323 rect.SetY(box->Root().SelectionTop()); | 1325 return LocalCaretRect( | 
| 1324 rect.SetHeight(box->Root().SelectionHeight()); | 1326 layout_object, | 
| 1325 return rect; | 1327 LayoutRect(LayoutPoint(rect.X(), box->Root().SelectionTop()), | 
| 1328 LayoutSize(rect.Width(), box->Root().SelectionHeight()))); | |
| 1326 } | 1329 } | 
| 1327 | 1330 | 
| 1328 rect.SetX(box->Root().SelectionTop()); | 1331 return LocalCaretRect( | 
| 1329 rect.SetWidth(box->Root().SelectionHeight()); | 1332 layout_object, | 
| 1330 return rect; | 1333 LayoutRect(LayoutPoint(box->Root().SelectionTop(), rect.Y()), | 
| 1334 LayoutSize(box->Root().SelectionHeight(), rect.Height()))); | |
| 1331 } | 1335 } | 
| 1332 | 1336 | 
| 1333 LayoutRect LocalCaretRectOfPosition(const PositionWithAffinity& position, | 1337 LocalCaretRect LocalCaretRectOfPosition(const PositionWithAffinity& position) { | 
| 1334 LayoutObject*& layout_object) { | 1338 return LocalCaretRectOfPositionTemplate<EditingStrategy>(position); | 
| 1335 return LocalCaretRectOfPositionTemplate<EditingStrategy>(position, | |
| 1336 layout_object); | |
| 1337 } | 1339 } | 
| 1338 | 1340 | 
| 1339 LayoutRect LocalSelectionRectOfPosition(const PositionWithAffinity& position, | 1341 static LocalCaretRect LocalSelectionRectOfPosition( | 
| 1340 LayoutObject*& layout_object) { | 1342 const PositionWithAffinity& position) { | 
| 1341 return LocalSelectionRectOfPositionTemplate<EditingStrategy>(position, | 1343 return LocalSelectionRectOfPositionTemplate<EditingStrategy>(position); | 
| 1342 layout_object); | |
| 1343 } | 1344 } | 
| 1344 | 1345 | 
| 1345 LayoutRect LocalCaretRectOfPosition( | 1346 LocalCaretRect LocalCaretRectOfPosition( | 
| 1346 const PositionInFlatTreeWithAffinity& position, | 1347 const PositionInFlatTreeWithAffinity& position) { | 
| 1347 LayoutObject*& layout_object) { | 1348 return LocalCaretRectOfPositionTemplate<EditingInFlatTreeStrategy>(position); | 
| 1348 return LocalCaretRectOfPositionTemplate<EditingInFlatTreeStrategy>( | |
| 1349 position, layout_object); | |
| 1350 } | 1349 } | 
| 1351 | 1350 | 
| 1352 static LayoutUnit BoundingBoxLogicalHeight(LayoutObject* o, | 1351 static LayoutUnit BoundingBoxLogicalHeight(LayoutObject* o, | 
| 1353 const LayoutRect& rect) { | 1352 const LayoutRect& rect) { | 
| 1354 return o->Style()->IsHorizontalWritingMode() ? rect.Height() : rect.Width(); | 1353 return o->Style()->IsHorizontalWritingMode() ? rect.Height() : rect.Width(); | 
| 1355 } | 1354 } | 
| 1356 | 1355 | 
| 1357 bool HasRenderedNonAnonymousDescendantsWithHeight(LayoutObject* layout_object) { | 1356 bool HasRenderedNonAnonymousDescendantsWithHeight(LayoutObject* layout_object) { | 
| 1358 LayoutObject* stop = layout_object->NextInPreOrderAfterChildren(); | 1357 LayoutObject* stop = layout_object->NextInPreOrderAfterChildren(); | 
| 1359 for (LayoutObject* o = layout_object->SlowFirstChild(); o && o != stop; | 1358 for (LayoutObject* o = layout_object->SlowFirstChild(); o && o != stop; | 
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1480 return text_offset == text_layout_object->CaretMinOffset() || | 1479 return text_offset == text_layout_object->CaretMinOffset() || | 
| 1481 text_offset == NextGraphemeBoundaryOf( | 1480 text_offset == NextGraphemeBoundaryOf( | 
| 1482 anchor_node, PreviousGraphemeBoundaryOf( | 1481 anchor_node, PreviousGraphemeBoundaryOf( | 
| 1483 anchor_node, text_offset)); | 1482 anchor_node, text_offset)); | 
| 1484 } | 1483 } | 
| 1485 } | 1484 } | 
| 1486 | 1485 | 
| 1487 return false; | 1486 return false; | 
| 1488 } | 1487 } | 
| 1489 | 1488 | 
| 1489 FloatQuad LocalCaretRect::LocalToAbsoluteQuad() const { | |
| 1490 return layout_object->LocalToAbsoluteQuad(FloatRect(rect)); | |
| 1491 } | |
| 1492 | |
| 1490 bool RendersInDifferentPosition(const Position& position1, | 1493 bool RendersInDifferentPosition(const Position& position1, | 
| 1491 const Position& position2) { | 1494 const Position& position2) { | 
| 1492 if (position1.IsNull() || position2.IsNull()) | 1495 if (position1.IsNull() || position2.IsNull()) | 
| 1493 return false; | 1496 return false; | 
| 1494 LayoutObject* layout_object1; | 1497 const LocalCaretRect& caret_rect1 = | 
| 1495 const LayoutRect& rect1 = | 1498 LocalCaretRectOfPosition(PositionWithAffinity(position1)); | 
| 1496 LocalCaretRectOfPosition(PositionWithAffinity(position1), layout_object1); | 1499 const LocalCaretRect& caret_rect2 = | 
| 1497 LayoutObject* layout_object2; | 1500 LocalCaretRectOfPosition(PositionWithAffinity(position2)); | 
| 1498 const LayoutRect& rect2 = | 1501 if (!caret_rect1.layout_object || !caret_rect2.layout_object) | 
| 1499 LocalCaretRectOfPosition(PositionWithAffinity(position2), layout_object2); | 1502 return caret_rect1.layout_object != caret_rect2.layout_object; | 
| 1500 if (!layout_object1 || !layout_object2) | 1503 return caret_rect1.LocalToAbsoluteQuad() != caret_rect2.LocalToAbsoluteQuad(); | 
| 1501 return layout_object1 != layout_object2; | |
| 1502 return layout_object1->LocalToAbsoluteQuad(FloatRect(rect1)) != | |
| 1503 layout_object2->LocalToAbsoluteQuad(FloatRect(rect2)); | |
| 1504 } | 1504 } | 
| 1505 | 1505 | 
| 1506 static bool IsVisuallyEmpty(const LayoutObject* layout) { | 1506 static bool IsVisuallyEmpty(const LayoutObject* layout) { | 
| 1507 for (LayoutObject* child = layout->SlowFirstChild(); child; | 1507 for (LayoutObject* child = layout->SlowFirstChild(); child; | 
| 1508 child = child->NextSibling()) { | 1508 child = child->NextSibling()) { | 
| 1509 // TODO(xiaochengh): Replace type-based conditioning by virtual function. | 1509 // TODO(xiaochengh): Replace type-based conditioning by virtual function. | 
| 1510 if (child->IsBox()) { | 1510 if (child->IsBox()) { | 
| 1511 if (!ToLayoutBox(child)->Size().IsEmpty()) | 1511 if (!ToLayoutBox(child)->Size().IsEmpty()) | 
| 1512 return false; | 1512 return false; | 
| 1513 } else if (child->IsLayoutInline()) { | 1513 } else if (child->IsLayoutInline()) { | 
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2007 | 2007 | 
| 2008 bool IsVisuallyEquivalentCandidate(const PositionInFlatTree& position) { | 2008 bool IsVisuallyEquivalentCandidate(const PositionInFlatTree& position) { | 
| 2009 return IsVisuallyEquivalentCandidateAlgorithm<EditingInFlatTreeStrategy>( | 2009 return IsVisuallyEquivalentCandidateAlgorithm<EditingInFlatTreeStrategy>( | 
| 2010 position); | 2010 position); | 
| 2011 } | 2011 } | 
| 2012 | 2012 | 
| 2013 template <typename Strategy> | 2013 template <typename Strategy> | 
| 2014 static IntRect AbsoluteCaretBoundsOfAlgorithm( | 2014 static IntRect AbsoluteCaretBoundsOfAlgorithm( | 
| 2015 const VisiblePositionTemplate<Strategy>& visible_position) { | 2015 const VisiblePositionTemplate<Strategy>& visible_position) { | 
| 2016 DCHECK(visible_position.IsValid()) << visible_position; | 2016 DCHECK(visible_position.IsValid()) << visible_position; | 
| 2017 LayoutObject* layout_object; | 2017 const LocalCaretRect& caret_rect = | 
| 2018 LayoutRect local_rect = LocalCaretRectOfPosition( | 2018 LocalCaretRectOfPosition(visible_position.ToPositionWithAffinity()); | 
| 2019 visible_position.ToPositionWithAffinity(), layout_object); | 2019 if (caret_rect.IsEmpty()) | 
| 2020 if (local_rect.IsEmpty() || !layout_object) | |
| 2021 return IntRect(); | 2020 return IntRect(); | 
| 2022 | 2021 return caret_rect.LocalToAbsoluteQuad().EnclosingBoundingBox(); | 
| 2023 return layout_object->LocalToAbsoluteQuad(FloatRect(local_rect)) | |
| 2024 .EnclosingBoundingBox(); | |
| 2025 } | 2022 } | 
| 2026 | 2023 | 
| 2027 IntRect AbsoluteCaretBoundsOf(const VisiblePosition& visible_position) { | 2024 IntRect AbsoluteCaretBoundsOf(const VisiblePosition& visible_position) { | 
| 2028 return AbsoluteCaretBoundsOfAlgorithm<EditingStrategy>(visible_position); | 2025 return AbsoluteCaretBoundsOfAlgorithm<EditingStrategy>(visible_position); | 
| 2029 } | 2026 } | 
| 2030 | 2027 | 
| 2031 template <typename Strategy> | 2028 template <typename Strategy> | 
| 2032 static IntRect AbsoluteSelectionBoundsOfAlgorithm( | 2029 static IntRect AbsoluteSelectionBoundsOfAlgorithm( | 
| 2033 const VisiblePositionTemplate<Strategy>& visible_position) { | 2030 const VisiblePositionTemplate<Strategy>& visible_position) { | 
| 2034 DCHECK(visible_position.IsValid()) << visible_position; | 2031 DCHECK(visible_position.IsValid()) << visible_position; | 
| 2035 LayoutObject* layout_object; | 2032 const LocalCaretRect& caret_rect = | 
| 2036 LayoutRect local_rect = LocalSelectionRectOfPosition( | 2033 LocalSelectionRectOfPosition(visible_position.ToPositionWithAffinity()); | 
| 2037 visible_position.ToPositionWithAffinity(), layout_object); | 2034 if (caret_rect.IsEmpty()) | 
| 2038 if (local_rect.IsEmpty() || !layout_object) | |
| 2039 return IntRect(); | 2035 return IntRect(); | 
| 2040 | 2036 return caret_rect.LocalToAbsoluteQuad().EnclosingBoundingBox(); | 
| 2041 return layout_object->LocalToAbsoluteQuad(FloatRect(local_rect)) | |
| 2042 .EnclosingBoundingBox(); | |
| 2043 } | 2037 } | 
| 2044 | 2038 | 
| 2045 IntRect AbsoluteSelectionBoundsOf(const VisiblePosition& visible_position) { | 2039 IntRect AbsoluteSelectionBoundsOf(const VisiblePosition& visible_position) { | 
| 2046 return AbsoluteSelectionBoundsOfAlgorithm<EditingStrategy>(visible_position); | 2040 return AbsoluteSelectionBoundsOfAlgorithm<EditingStrategy>(visible_position); | 
| 2047 } | 2041 } | 
| 2048 | 2042 | 
| 2049 IntRect AbsoluteCaretBoundsOf( | 2043 IntRect AbsoluteCaretBoundsOf( | 
| 2050 const VisiblePositionInFlatTree& visible_position) { | 2044 const VisiblePositionInFlatTree& visible_position) { | 
| 2051 return AbsoluteCaretBoundsOfAlgorithm<EditingInFlatTreeStrategy>( | 2045 return AbsoluteCaretBoundsOfAlgorithm<EditingInFlatTreeStrategy>( | 
| 2052 visible_position); | 2046 visible_position); | 
| (...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2772 | 2766 | 
| 2773 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { | 2767 IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) { | 
| 2774 return EnclosingIntRect(ComputeTextRectTemplate(range)); | 2768 return EnclosingIntRect(ComputeTextRectTemplate(range)); | 
| 2775 } | 2769 } | 
| 2776 | 2770 | 
| 2777 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { | 2771 FloatRect ComputeTextFloatRect(const EphemeralRange& range) { | 
| 2778 return ComputeTextRectTemplate(range); | 2772 return ComputeTextRectTemplate(range); | 
| 2779 } | 2773 } | 
| 2780 | 2774 | 
| 2781 } // namespace blink | 2775 } // namespace blink | 
| OLD | NEW |