| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple 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 | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 | 169 |
| 170 return true; | 170 return true; |
| 171 } | 171 } |
| 172 | 172 |
| 173 bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co
nst LayoutRect& rect, const LayoutPoint& offset, LayoutUnit outlineSize) const | 173 bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co
nst LayoutRect& rect, const LayoutPoint& offset, LayoutUnit outlineSize) const |
| 174 { | 174 { |
| 175 // We can check the first box and last box and avoid painting/hit testing if
we don't | 175 // We can check the first box and last box and avoid painting/hit testing if
we don't |
| 176 // intersect. This is a quick short-circuit that we can take to avoid walki
ng any lines. | 176 // intersect. This is a quick short-circuit that we can take to avoid walki
ng any lines. |
| 177 // FIXME: This check is flawed in the following extremely obscure way: | 177 // FIXME: This check is flawed in the following extremely obscure way: |
| 178 // if some line in the middle has a huge overflow, it might actually extend
below the last line. | 178 // if some line in the middle has a huge overflow, it might actually extend
below the last line. |
| 179 RootInlineBox* firstRootBox = firstLineBox()->root(); | 179 RootInlineBox& firstRootBox = firstLineBox()->root(); |
| 180 RootInlineBox* lastRootBox = lastLineBox()->root(); | 180 RootInlineBox& lastRootBox = lastLineBox()->root(); |
| 181 LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRoot
Box->lineTop()); | 181 LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRoot
Box.lineTop()); |
| 182 LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastR
ootBox->lineBottom()); | 182 LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastR
ootBox.lineBottom()); |
| 183 LayoutUnit logicalTop = firstLineTop - outlineSize; | 183 LayoutUnit logicalTop = firstLineTop - outlineSize; |
| 184 LayoutUnit logicalBottom = outlineSize + lastLineBottom; | 184 LayoutUnit logicalBottom = outlineSize + lastLineBottom; |
| 185 | 185 |
| 186 return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset
); | 186 return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset
); |
| 187 } | 187 } |
| 188 | 188 |
| 189 bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer,
InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const | 189 bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer,
InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const |
| 190 { | 190 { |
| 191 RootInlineBox* root = box->root(); | 191 RootInlineBox& root = box->root(); |
| 192 LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root->
lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase
); | 192 LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root.l
ineTop()), root.selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase); |
| 193 LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom
()) + renderer->maximalOutlineSize(paintInfo.phase); | 193 LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root.lineBottom(
)) + renderer->maximalOutlineSize(paintInfo.phase); |
| 194 | 194 |
| 195 return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.re
ct, offset); | 195 return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.re
ct, offset); |
| 196 } | 196 } |
| 197 | 197 |
| 198 void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
fo, const LayoutPoint& paintOffset) const | 198 void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
fo, const LayoutPoint& paintOffset) const |
| 199 { | 199 { |
| 200 // Only paint during the foreground/selection phases. | 200 // Only paint during the foreground/selection phases. |
| 201 if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhase
Selection && paintInfo.phase != PaintPhaseOutline | 201 if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhase
Selection && paintInfo.phase != PaintPhaseOutline |
| 202 && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines && paintInfo.phase != PaintPhaseTextClip | 202 && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintP
haseChildOutlines && paintInfo.phase != PaintPhaseTextClip |
| 203 && paintInfo.phase != PaintPhaseMask) | 203 && paintInfo.phase != PaintPhaseMask) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 215 | 215 |
| 216 PaintInfo info(paintInfo); | 216 PaintInfo info(paintInfo); |
| 217 ListHashSet<RenderInline*> outlineObjects; | 217 ListHashSet<RenderInline*> outlineObjects; |
| 218 info.setOutlineObjects(&outlineObjects); | 218 info.setOutlineObjects(&outlineObjects); |
| 219 | 219 |
| 220 // See if our root lines intersect with the dirty rect. If so, then we pain
t | 220 // See if our root lines intersect with the dirty rect. If so, then we pain
t |
| 221 // them. Note that boxes can easily overlap, so we can't make any assumptio
ns | 221 // them. Note that boxes can easily overlap, so we can't make any assumptio
ns |
| 222 // based off positions of our first line box or our last line box. | 222 // based off positions of our first line box or our last line box. |
| 223 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
{ | 223 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
{ |
| 224 if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) { | 224 if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) { |
| 225 RootInlineBox* root = curr->root(); | 225 RootInlineBox& root = curr->root(); |
| 226 curr->paint(info, paintOffset, root->lineTop(), root->lineBottom()); | 226 curr->paint(info, paintOffset, root.lineTop(), root.lineBottom()); |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 | 229 |
| 230 if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline |
| info.phase == PaintPhaseChildOutlines) { | 230 if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline |
| info.phase == PaintPhaseChildOutlines) { |
| 231 ListHashSet<RenderInline*>::iterator end = info.outlineObjects()->end(); | 231 ListHashSet<RenderInline*>::iterator end = info.outlineObjects()->end(); |
| 232 for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects()->be
gin(); it != end; ++it) { | 232 for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects()->be
gin(); it != end; ++it) { |
| 233 RenderInline* flow = *it; | 233 RenderInline* flow = *it; |
| 234 flow->paintOutline(info, paintOffset); | 234 flow->paintOutline(info, paintOffset); |
| 235 } | 235 } |
| 236 info.outlineObjects()->clear(); | 236 info.outlineObjects()->clear(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 253 IntRect(point.x(), point.y() - locationInContainer.topPadding(), 1, loca
tionInContainer.topPadding() + locationInContainer.bottomPadding() + 1) : | 253 IntRect(point.x(), point.y() - locationInContainer.topPadding(), 1, loca
tionInContainer.topPadding() + locationInContainer.bottomPadding() + 1) : |
| 254 IntRect(point.x() - locationInContainer.leftPadding(), point.y(), locati
onInContainer.rightPadding() + locationInContainer.leftPadding() + 1, 1); | 254 IntRect(point.x() - locationInContainer.leftPadding(), point.y(), locati
onInContainer.rightPadding() + locationInContainer.leftPadding() + 1, 1); |
| 255 | 255 |
| 256 if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset)) | 256 if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset)) |
| 257 return false; | 257 return false; |
| 258 | 258 |
| 259 // See if our root lines contain the point. If so, then we hit test | 259 // See if our root lines contain the point. If so, then we hit test |
| 260 // them further. Note that boxes can easily overlap, so we can't make any a
ssumptions | 260 // them further. Note that boxes can easily overlap, so we can't make any a
ssumptions |
| 261 // based off positions of our first line box or our last line box. | 261 // based off positions of our first line box or our last line box. |
| 262 for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox())
{ | 262 for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox())
{ |
| 263 RootInlineBox* root = curr->root(); | 263 RootInlineBox& root = curr->root(); |
| 264 if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root->l
ineTop()), curr->logicalBottomVisualOverflow(root->lineBottom()), rect, accumula
tedOffset)) { | 264 if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root.li
neTop()), curr->logicalBottomVisualOverflow(root.lineBottom()), rect, accumulate
dOffset)) { |
| 265 bool inside = curr->nodeAtPoint(request, result, locationInContainer
, accumulatedOffset, root->lineTop(), root->lineBottom()); | 265 bool inside = curr->nodeAtPoint(request, result, locationInContainer
, accumulatedOffset, root.lineTop(), root.lineBottom()); |
| 266 if (inside) { | 266 if (inside) { |
| 267 renderer->updateHitTestResult(result, locationInContainer.point(
) - toLayoutSize(accumulatedOffset)); | 267 renderer->updateHitTestResult(result, locationInContainer.point(
) - toLayoutSize(accumulatedOffset)); |
| 268 return true; | 268 return true; |
| 269 } | 269 } |
| 270 } | 270 } |
| 271 } | 271 } |
| 272 | 272 |
| 273 return false; | 273 return false; |
| 274 } | 274 } |
| 275 | 275 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 297 // parent's first line box. | 297 // parent's first line box. |
| 298 RootInlineBox* box = 0; | 298 RootInlineBox* box = 0; |
| 299 RenderObject* curr = 0; | 299 RenderObject* curr = 0; |
| 300 for (curr = child->previousSibling(); curr; curr = curr->previousSibling())
{ | 300 for (curr = child->previousSibling(); curr; curr = curr->previousSibling())
{ |
| 301 if (curr->isFloatingOrOutOfFlowPositioned()) | 301 if (curr->isFloatingOrOutOfFlowPositioned()) |
| 302 continue; | 302 continue; |
| 303 | 303 |
| 304 if (curr->isReplaced()) { | 304 if (curr->isReplaced()) { |
| 305 InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper(); | 305 InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper(); |
| 306 if (wrapper) | 306 if (wrapper) |
| 307 box = wrapper->root(); | 307 box = &wrapper->root(); |
| 308 } else if (curr->isText()) { | 308 } else if (curr->isText()) { |
| 309 InlineTextBox* textBox = toRenderText(curr)->lastTextBox(); | 309 InlineTextBox* textBox = toRenderText(curr)->lastTextBox(); |
| 310 if (textBox) | 310 if (textBox) |
| 311 box = textBox->root(); | 311 box = &textBox->root(); |
| 312 } else if (curr->isRenderInline()) { | 312 } else if (curr->isRenderInline()) { |
| 313 InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludi
ngCulling(); | 313 InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludi
ngCulling(); |
| 314 if (lastSiblingBox) | 314 if (lastSiblingBox) |
| 315 box = lastSiblingBox->root(); | 315 box = &lastSiblingBox->root(); |
| 316 } | 316 } |
| 317 | 317 |
| 318 if (box) | 318 if (box) |
| 319 break; | 319 break; |
| 320 } | 320 } |
| 321 if (!box) { | 321 if (!box) { |
| 322 if (inlineContainer && !inlineContainer->alwaysCreateLineBoxes()) { | 322 if (inlineContainer && !inlineContainer->alwaysCreateLineBoxes()) { |
| 323 // https://bugs.webkit.org/show_bug.cgi?id=60778 | 323 // https://bugs.webkit.org/show_bug.cgi?id=60778 |
| 324 // We may have just removed a <br> with no line box that was our fir
st child. In this case | 324 // We may have just removed a <br> with no line box that was our fir
st child. In this case |
| 325 // we won't find a previous sibling, but firstBox can be pointing to
a following sibling. | 325 // we won't find a previous sibling, but firstBox can be pointing to
a following sibling. |
| 326 // This isn't good enough, since we won't locate the root line box t
hat encloses the removed | 326 // This isn't good enough, since we won't locate the root line box t
hat encloses the removed |
| 327 // <br>. We have to just over-invalidate a bit and go up to our pare
nt. | 327 // <br>. We have to just over-invalidate a bit and go up to our pare
nt. |
| 328 if (!inlineContainer->ancestorLineBoxDirty()) { | 328 if (!inlineContainer->ancestorLineBoxDirty()) { |
| 329 inlineContainer->parent()->dirtyLinesFromChangedChild(inlineCont
ainer); | 329 inlineContainer->parent()->dirtyLinesFromChangedChild(inlineCont
ainer); |
| 330 inlineContainer->setAncestorLineBoxDirty(); // Mark the containe
r to avoid dirtying the same lines again across multiple destroy() calls of the
same subtree. | 330 inlineContainer->setAncestorLineBoxDirty(); // Mark the containe
r to avoid dirtying the same lines again across multiple destroy() calls of the
same subtree. |
| 331 } | 331 } |
| 332 return; | 332 return; |
| 333 } | 333 } |
| 334 box = firstBox->root(); | 334 box = &firstBox->root(); |
| 335 } | 335 } |
| 336 | 336 |
| 337 // If we found a line box, then dirty it. | 337 // If we found a line box, then dirty it. |
| 338 if (box) { | 338 if (box) { |
| 339 RootInlineBox* adjacentBox; | 339 RootInlineBox* adjacentBox; |
| 340 box->markDirty(); | 340 box->markDirty(); |
| 341 | 341 |
| 342 // dirty the adjacent lines that might be affected | 342 // dirty the adjacent lines that might be affected |
| 343 // NOTE: we dirty the previous line because RootInlineBox objects cache | 343 // NOTE: we dirty the previous line because RootInlineBox objects cache |
| 344 // the address of the first object on the next line after a BR, which we
may be | 344 // the address of the first object on the next line after a BR, which we
may be |
| (...skipping 26 matching lines...) Expand all Loading... |
| 371 ASSERT(child->prevLineBox() == prev); | 371 ASSERT(child->prevLineBox() == prev); |
| 372 prev = child; | 372 prev = child; |
| 373 } | 373 } |
| 374 ASSERT(prev == m_lastLineBox); | 374 ASSERT(prev == m_lastLineBox); |
| 375 #endif | 375 #endif |
| 376 } | 376 } |
| 377 | 377 |
| 378 #endif | 378 #endif |
| 379 | 379 |
| 380 } | 380 } |
| OLD | NEW |