OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 13 matching lines...) Expand all Loading... |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "core/layout/LayoutBlockFlow.h" | 31 #include "core/layout/LayoutBlockFlow.h" |
32 | 32 |
33 #include "core/dom/AXObjectCache.h" | 33 #include "core/dom/AXObjectCache.h" |
| 34 #include "core/editing/Editor.h" |
34 #include "core/frame/FrameView.h" | 35 #include "core/frame/FrameView.h" |
35 #include "core/frame/LocalFrame.h" | 36 #include "core/frame/LocalFrame.h" |
36 #include "core/frame/Settings.h" | 37 #include "core/frame/Settings.h" |
37 #include "core/html/HTMLDialogElement.h" | 38 #include "core/html/HTMLDialogElement.h" |
38 #include "core/layout/HitTestLocation.h" | 39 #include "core/layout/HitTestLocation.h" |
39 #include "core/layout/LayoutAnalyzer.h" | 40 #include "core/layout/LayoutAnalyzer.h" |
40 #include "core/layout/LayoutFlowThread.h" | 41 #include "core/layout/LayoutFlowThread.h" |
41 #include "core/layout/LayoutMultiColumnFlowThread.h" | 42 #include "core/layout/LayoutMultiColumnFlowThread.h" |
42 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" | 43 #include "core/layout/LayoutMultiColumnSpannerPlaceholder.h" |
43 #include "core/layout/LayoutPagedFlowThread.h" | 44 #include "core/layout/LayoutPagedFlowThread.h" |
(...skipping 3129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3173 | 3174 |
3174 // FIXME: Glyph overflow will get lost in this case, but not really a big de
al. | 3175 // FIXME: Glyph overflow will get lost in this case, but not really a big de
al. |
3175 GlyphOverflowAndFallbackFontsMap textBoxDataMap; | 3176 GlyphOverflowAndFallbackFontsMap textBoxDataMap; |
3176 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it
!= lineBoxes.end(); ++it) { | 3177 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it
!= lineBoxes.end(); ++it) { |
3177 RootInlineBox* box = *it; | 3178 RootInlineBox* box = *it; |
3178 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); | 3179 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap); |
3179 } | 3180 } |
3180 return childrenOverflowChanged; | 3181 return childrenOverflowChanged; |
3181 } | 3182 } |
3182 | 3183 |
| 3184 PositionWithAffinity LayoutBlockFlow::positionForPoint(const LayoutPoint& point) |
| 3185 { |
| 3186 if (isAtomicInlineLevel()) { |
| 3187 PositionWithAffinity position = positionForPointIfOutsideAtomicInlineLev
el(point); |
| 3188 if (!position.isNull()) |
| 3189 return position; |
| 3190 } |
| 3191 if (!childrenInline()) |
| 3192 return LayoutBlock::positionForPoint(point); |
| 3193 |
| 3194 LayoutPoint pointInContents = point; |
| 3195 offsetForContents(pointInContents); |
| 3196 LayoutPoint pointInLogicalContents(pointInContents); |
| 3197 if (!isHorizontalWritingMode()) |
| 3198 pointInLogicalContents = pointInLogicalContents.transposedPoint(); |
| 3199 |
| 3200 if (!firstRootBox()) |
| 3201 return createPositionWithAffinity(0); |
| 3202 |
| 3203 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); |
| 3204 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); |
| 3205 |
| 3206 // look for the closest line box in the root box which is at the passed-in y
coordinate |
| 3207 InlineBox* closestBox = nullptr; |
| 3208 RootInlineBox* firstRootBoxWithChildren = nullptr; |
| 3209 RootInlineBox* lastRootBoxWithChildren = nullptr; |
| 3210 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox())
{ |
| 3211 if (!root->firstLeafChild()) |
| 3212 continue; |
| 3213 if (!firstRootBoxWithChildren) |
| 3214 firstRootBoxWithChildren = root; |
| 3215 |
| 3216 if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogical
Contents.y() < root->lineTopWithLeading() |
| 3217 || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopW
ithLeading()))) |
| 3218 break; |
| 3219 |
| 3220 lastRootBoxWithChildren = root; |
| 3221 |
| 3222 // check if this root line box is located at this y coordinate |
| 3223 if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFl
ipped && pointInLogicalContents.y() == root->selectionBottom())) { |
| 3224 if (linesAreFlipped) { |
| 3225 RootInlineBox* nextRootBoxWithChildren = root->nextRootBox(); |
| 3226 while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firs
tLeafChild()) |
| 3227 nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootB
ox(); |
| 3228 |
| 3229 if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstA
fterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTo
pWithLeading() |
| 3230 || (!blocksAreFlipped && pointInLogicalContents.y() == nextR
ootBoxWithChildren->lineTopWithLeading()))) |
| 3231 continue; |
| 3232 } |
| 3233 closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLog
icalContents.x()); |
| 3234 if (closestBox) |
| 3235 break; |
| 3236 } |
| 3237 } |
| 3238 |
| 3239 bool moveCaretToBoundary = document().frame()->editor().behavior().shouldMov
eCaretToHorizontalBoundaryWhenPastTopOrBottom(); |
| 3240 |
| 3241 if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) { |
| 3242 // y coordinate is below last root line box, pretend we hit it |
| 3243 closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosi
tion(pointInLogicalContents.x()); |
| 3244 } |
| 3245 |
| 3246 if (closestBox) { |
| 3247 if (moveCaretToBoundary) { |
| 3248 LayoutUnit firstRootBoxWithChildrenTop = std::min<LayoutUnit>(firstR
ootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop()); |
| 3249 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop |
| 3250 || (blocksAreFlipped && pointInLogicalContents.y() == firstRootB
oxWithChildrenTop)) { |
| 3251 InlineBox* box = firstRootBoxWithChildren->firstLeafChild(); |
| 3252 if (box->isLineBreak()) { |
| 3253 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak(
)) |
| 3254 box = newBox; |
| 3255 } |
| 3256 // y coordinate is above first root line box, so return the star
t of the first |
| 3257 return PositionWithAffinity(positionForBox(box, true)); |
| 3258 } |
| 3259 } |
| 3260 |
| 3261 // pass the box a top position that is inside it |
| 3262 LayoutPoint point(pointInLogicalContents.x(), closestBox->root().blockDi
rectionPointInLine()); |
| 3263 if (!isHorizontalWritingMode()) |
| 3264 point = point.transposedPoint(); |
| 3265 if (closestBox->getLineLayoutItem().isAtomicInlineLevel()) |
| 3266 return positionForPointRespectingEditingBoundaries(LineLayoutBox(clo
sestBox->getLineLayoutItem()), point); |
| 3267 return closestBox->getLineLayoutItem().positionForPoint(point); |
| 3268 } |
| 3269 |
| 3270 if (lastRootBoxWithChildren) { |
| 3271 // We hit this case for Mac behavior when the Y coordinate is below the
last box. |
| 3272 ASSERT(moveCaretToBoundary); |
| 3273 InlineBox* logicallyLastBox; |
| 3274 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox)) |
| 3275 return PositionWithAffinity(positionForBox(logicallyLastBox, false))
; |
| 3276 } |
| 3277 |
| 3278 // Can't reach this. We have a root line box, but it has no kids. |
| 3279 // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text |
| 3280 // seems to hit this code path. |
| 3281 return createPositionWithAffinity(0); |
| 3282 } |
| 3283 |
3183 #ifndef NDEBUG | 3284 #ifndef NDEBUG |
3184 | 3285 |
3185 void LayoutBlockFlow::showLineTreeAndMark(const InlineBox* markedBox1, const cha
r* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const La
youtObject* obj) const | 3286 void LayoutBlockFlow::showLineTreeAndMark(const InlineBox* markedBox1, const cha
r* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const La
youtObject* obj) const |
3186 { | 3287 { |
3187 showLayoutObject(); | 3288 showLayoutObject(); |
3188 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) | 3289 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) |
3189 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); | 3290 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); |
3190 } | 3291 } |
3191 | 3292 |
3192 #endif | 3293 #endif |
3193 | 3294 |
3194 } // namespace blink | 3295 } // namespace blink |
OLD | NEW |