Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(574)

Side by Side Diff: Source/core/rendering/RenderBlockFlow.cpp

Issue 166033009: *** FOR PROTOTYPE PURPOSES ONLY! NOT INTENDED FOR COMMIT! *** (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 // If we are self-collapsing with self-collapsing descendants this will get set to save us burrowing through our 275 // If we are self-collapsing with self-collapsing descendants this will get set to save us burrowing through our
276 // descendants every time in |isSelfCollapsingBlock|. We reset it here so th at |isSelfCollapsingBlock| attempts to burrow 276 // descendants every time in |isSelfCollapsingBlock|. We reset it here so th at |isSelfCollapsingBlock| attempts to burrow
277 // at least once and so that it always gives a reliable result reflecting th e latest layout. 277 // at least once and so that it always gives a reliable result reflecting th e latest layout.
278 m_hasOnlySelfCollapsingChildren = false; 278 m_hasOnlySelfCollapsingChildren = false;
279 279
280 if (!relayoutChildren && simplifiedLayout()) 280 if (!relayoutChildren && simplifiedLayout())
281 return; 281 return;
282 282
283 SubtreeLayoutScope layoutScope(this); 283 SubtreeLayoutScope layoutScope(this);
284 284
285 m_layoutScope = &layoutScope;
286 m_pageLogicalHeight = 0;
287
288 preLayoutBlock(relayoutChildren, true);
289
285 // Multiple passes might be required for column and pagination based layout 290 // Multiple passes might be required for column and pagination based layout
286 // In the case of the old column code the number of passes will only be two 291 // In the case of the old column code the number of passes will only be two
287 // however, in the newer column code the number of passes could equal the 292 // however, in the newer column code the number of passes could equal the
288 // number of columns. 293 // number of columns.
289 bool done = false; 294 bool done = postLayoutBlock();
290 LayoutUnit pageLogicalHeight = 0; 295 while (!done) {
291 while (!done) 296 preLayoutBlock(relayoutChildren, true);
292 done = layoutBlockFlow(relayoutChildren, pageLogicalHeight, layoutScope) ; 297 done = postLayoutBlock();
298 }
299 m_layoutScope = 0;
293 } 300 }
294 301
295 inline bool RenderBlockFlow::layoutBlockFlow(bool relayoutChildren, LayoutUnit & pageLogicalHeight, SubtreeLayoutScope& layoutScope) 302 void RenderBlockFlow::preLayoutBlock(bool relayoutChildren, bool traverseChildre n)
296 { 303 {
297 LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); 304 m_relayoutChildren = relayoutChildren;
305 preLayoutBlockFlow(traverseChildren);
306 }
307
308 bool RenderBlockFlow::postLayoutBlock()
309 {
310 return postLayoutBlockFlow();
311 }
312
313 void RenderBlockFlow::preLayoutBlockFlow(bool traverseChildren)
314 {
315 m_checkForRepaint = checkForRepaintDuringLayout();
316 m_oldBounds = LayoutRect();
317 m_oldOutlineBox = LayoutRect();
318 if (m_checkForRepaint) {
319 m_oldBounds = clippedOverflowRectForRepaint(containerForRepaint());
320 m_oldOutlineBox = outlineBoundsForRepaint(containerForRepaint(), 0);
321 }
298 322
299 if (updateLogicalWidthAndColumnWidth()) 323 if (updateLogicalWidthAndColumnWidth())
300 relayoutChildren = true; 324 m_relayoutChildren = true;
301 325
302 rebuildFloatsFromIntruding(); 326 rebuildFloatsFromIntruding();
303 327
304 bool pageLogicalHeightChanged = false; 328 bool pageLogicalHeightChanged = false;
305 bool hasSpecifiedPageLogicalHeight = false; 329 m_hasSpecifiedPageLogicalHeight = false;
306 checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightCh anged, hasSpecifiedPageLogicalHeight); 330 checkForPaginationLogicalHeightChange(m_pageLogicalHeight, pageLogicalHeight Changed, m_hasSpecifiedPageLogicalHeight);
307 331
308 RenderView* renderView = view(); 332 RenderView* renderView = view();
309 LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasCol umns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMo de(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo()); 333 m_statePusher = new LayoutStateMaintainer(renderView, this, locationOffset() , hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksW ritingMode(), m_pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
310 334
311 // Regions changing widths can force us to relayout our children. 335 // Regions changing widths can force us to relayout our children.
312 RenderFlowThread* flowThread = flowThreadContainingBlock(); 336 RenderFlowThread* flowThread = flowThreadContainingBlock();
313 if (logicalWidthChangedInRegions(flowThread)) 337 if (logicalWidthChangedInRegions(flowThread))
314 relayoutChildren = true; 338 m_relayoutChildren = true;
315 if (updateRegionsAndShapesLogicalSize(flowThread)) 339 if (updateRegionsAndShapesLogicalSize(flowThread))
316 relayoutChildren = true; 340 m_relayoutChildren = true;
317 if (!relayoutChildren && isRenderNamedFlowFragmentContainer()) 341 if (!m_relayoutChildren && isRenderNamedFlowFragmentContainer())
318 relayoutChildren = true; 342 m_relayoutChildren = true;
319 343
320 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track 344 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
321 // our current maximal positive and negative margins. These values are used when we 345 // our current maximal positive and negative margins. These values are used when we
322 // are collapsed with adjacent blocks, so for example, if you have block A a nd B 346 // are collapsed with adjacent blocks, so for example, if you have block A a nd B
323 // collapsing together, then you'd take the maximal positive margin from bot h A and B 347 // collapsing together, then you'd take the maximal positive margin from bot h A and B
324 // and subtract it from the maximal negative margin from both A and B to get the 348 // and subtract it from the maximal negative margin from both A and B to get the
325 // true collapsed margin. This algorithm is recursive, so when we finish lay out() 349 // true collapsed margin. This algorithm is recursive, so when we finish lay out()
326 // our block knows its current maximal positive/negative values. 350 // our block knows its current maximal positive/negative values.
327 // 351 //
328 // Start out by setting our margin values to our current margins. Table cell s have 352 // Start out by setting our margin values to our current margins. Table cell s have
329 // no margins, so we don't fill in the values for table cells. 353 // no margins, so we don't fill in the values for table cells.
330 if (!isTableCell()) { 354 if (!isTableCell()) {
331 initMaxMarginValues(); 355 initMaxMarginValues();
332 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); 356 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk());
333 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); 357 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk());
334 setPaginationStrut(0); 358 setPaginationStrut(0);
335 } 359 }
336 360
337 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); 361 LayoutUnit beforeEdge = borderBefore() + paddingBefore();
338 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig ht(); 362 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig ht();
339 LayoutUnit previousHeight = logicalHeight(); 363 m_heightBeforeLayout = logicalHeight();
340 setLogicalHeight(beforeEdge); 364 setLogicalHeight(beforeEdge);
341 365
342 m_repaintLogicalTop = 0; 366 m_repaintLogicalTop = 0;
343 m_repaintLogicalBottom = 0; 367 m_repaintLogicalBottom = 0;
344 LayoutUnit maxFloatLogicalBottom = 0; 368 m_maxFloatLogicalBottom = 0;
345 if (!firstChild() && !isAnonymousBlock()) 369 if (!firstChild() && !isAnonymousBlock())
346 setChildrenInline(true); 370 setChildrenInline(true);
347 371
348 FastTextAutosizer* textAutosizer = document().fastTextAutosizer(); 372 FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
349 if (textAutosizer) 373 if (textAutosizer)
350 textAutosizer->beginLayout(this); 374 textAutosizer->beginLayout(this);
351 375
352 if (childrenInline()) 376 if (childrenInline())
353 layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLog icalBottom, afterEdge); 377 layoutInlineChildren(m_relayoutChildren, m_repaintLogicalTop, m_repaintL ogicalBottom, afterEdge);
354 else 378 else {
355 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom, layoutScope , beforeEdge, afterEdge); 379 dirtyForLayoutFromPercentageHeightDescendants(*m_layoutScope);
380
381 // Lay out our hypothetical grid line as though it occurs at the top of the block.
382 if (view()->layoutState()->lineGrid() == this)
383 layoutLineGridBox();
384
385 layoutBlockChildren(beforeEdge, afterEdge, traverseChildren);
386 }
387 }
388
389 bool RenderBlockFlow::postLayoutBlockFlow()
390 {
391 if (!m_statePusher) // simple layout
392 return true;
356 393
357 if (frameView()->partialLayout().isStopping()) { 394 if (frameView()->partialLayout().isStopping()) {
358 statePusher.pop(); 395 m_statePusher->pop();
396 delete m_statePusher;
397 m_statePusher = 0;
359 return true; 398 return true;
360 } 399 }
361 400
401 LayoutRepainter repainter(*this, m_checkForRepaint, m_oldBounds, m_oldOutlin eBox);
402 LayoutUnit beforeEdge = borderBefore() + paddingBefore();
403 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeig ht();
404
405 if (!childrenInline()) {
406 // Now do the handling of the bottom of the block, adding in our bottom border/padding and
407 // determining the correct collapsed bottom margin information.
408 handleAfterSideOfBlock(m_lastNormalFlowChild, beforeEdge, afterEdge, *m_ marginInfo);
409 delete m_marginInfo;
410 m_marginInfo = 0;
411 }
412
362 // Expand our intrinsic height to encompass floats. 413 // Expand our intrinsic height to encompass floats.
363 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && createsBlo ckFormattingContext()) 414 if (lowestFloatLogicalBottom() > (logicalHeight() - afterEdge) && createsBlo ckFormattingContext())
364 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge); 415 setLogicalHeight(lowestFloatLogicalBottom() + afterEdge);
365 416
366 if (isRenderMultiColumnBlock()) { 417 if (isRenderMultiColumnBlock()) {
367 if (toRenderMultiColumnBlock(this)->shouldRelayoutMultiColumnBlock()) { 418 if (toRenderMultiColumnBlock(this)->shouldRelayoutMultiColumnBlock()) {
368 setChildNeedsLayout(MarkOnlyThis); 419 setChildNeedsLayout(MarkOnlyThis);
369 statePusher.pop(); 420 m_statePusher->pop();
421 delete m_statePusher;
422 m_statePusher = 0;
370 return false; 423 return false;
371 } 424 }
372 } else if (hasColumns()) { 425 } else if (hasColumns()) {
373 OwnPtr<RenderOverflow> savedOverflow = m_overflow.release(); 426 OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
374 if (childrenInline()) 427 if (childrenInline())
375 addOverflowFromInlineChildren(); 428 addOverflowFromInlineChildren();
376 else 429 else
377 addOverflowFromBlockChildren(); 430 addOverflowFromBlockChildren();
378 LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? la youtOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - padd ingBefore(); 431 LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? la youtOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - padd ingBefore();
379 m_overflow = savedOverflow.release(); 432 m_overflow = savedOverflow.release();
380 433
381 if (!hasSpecifiedPageLogicalHeight && shouldRelayoutForPagination(pageLo gicalHeight, layoutOverflowLogicalBottom)) { 434 if (!m_hasSpecifiedPageLogicalHeight && shouldRelayoutForPagination(m_pa geLogicalHeight, layoutOverflowLogicalBottom)) {
382 statePusher.pop(); 435 m_statePusher->pop();
436 delete m_statePusher;
437 m_statePusher = 0;
383 setEverHadLayout(true); 438 setEverHadLayout(true);
384 return false; 439 return false;
385 } 440 }
386 441
387 setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageL ogicalHeight), pageLogicalHeight); 442 setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / m_pag eLogicalHeight), m_pageLogicalHeight);
388 } 443 }
389 444
390 if (shouldBreakAtLineToAvoidWidow()) { 445 if (shouldBreakAtLineToAvoidWidow()) {
391 statePusher.pop(); 446 m_statePusher->pop();
447 delete m_statePusher;
448 m_statePusher = 0;
392 setEverHadLayout(true); 449 setEverHadLayout(true);
393 return false; 450 return false;
394 } 451 }
395 452
396 // Calculate our new height. 453 // Calculate our new height.
397 LayoutUnit oldHeight = logicalHeight(); 454 LayoutUnit oldHeight = logicalHeight();
398 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); 455 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
399 456
400 // Before updating the final size of the flow thread make sure a forced brea k is applied after the content. 457 // Before updating the final size of the flow thread make sure a forced brea k is applied after the content.
401 // This ensures the size information is correctly computed for the last auto -height region receiving content. 458 // This ensures the size information is correctly computed for the last auto -height region receiving content.
402 if (isRenderFlowThread()) 459 if (isRenderFlowThread())
403 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge); 460 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge);
404 461
405 updateLogicalHeight(); 462 updateLogicalHeight();
406 LayoutUnit newHeight = logicalHeight(); 463 LayoutUnit newHeight = logicalHeight();
407 if (oldHeight != newHeight) { 464 if (oldHeight != newHeight) {
408 if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !child renInline()) { 465 if (oldHeight > newHeight && m_maxFloatLogicalBottom > newHeight && !chi ldrenInline()) {
409 // One of our children's floats may have become an overhanging float for us. We need to look for it. 466 // One of our children's floats may have become an overhanging float for us. We need to look for it.
410 for (RenderObject* child = firstChild(); child; child = child->nextS ibling()) { 467 for (RenderObject* child = firstChild(); child; child = child->nextS ibling()) {
411 if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowP ositioned()) { 468 if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowP ositioned()) {
412 RenderBlockFlow* block = toRenderBlockFlow(child); 469 RenderBlockFlow* block = toRenderBlockFlow(child);
413 if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight) 470 if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
414 addOverhangingFloats(block, false); 471 addOverhangingFloats(block, false);
415 } 472 }
416 } 473 }
417 } 474 }
418 } 475 }
419 476
420 bool heightChanged = (previousHeight != newHeight); 477 bool heightChanged = (m_heightBeforeLayout != newHeight);
421 if (heightChanged) 478 if (heightChanged)
422 relayoutChildren = true; 479 m_relayoutChildren = true;
423 480
424 layoutPositionedObjects(relayoutChildren || isRoot()); 481 layoutPositionedObjects(m_relayoutChildren || isRoot());
425 482
426 updateRegionsAndShapesAfterChildLayout(flowThread, heightChanged); 483 updateRegionsAndShapesAfterChildLayout(flowThreadContainingBlock(), heightCh anged);
427 484
428 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). 485 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
429 computeOverflow(oldClientAfterEdge); 486 computeOverflow(oldClientAfterEdge);
430 487
431 statePusher.pop(); 488 m_statePusher->pop();
432 489
433 fitBorderToLinesIfNeeded(); 490 fitBorderToLinesIfNeeded();
434 491
435 if (frameView()->partialLayout().isStopping()) 492 if (frameView()->partialLayout().isStopping()) {
493 delete m_statePusher;
494 m_statePusher = 0;
436 return true; 495 return true;
496 }
437 497
438 if (renderView->layoutState()->m_pageLogicalHeight) 498 if (view()->layoutState()->m_pageLogicalHeight)
439 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop())); 499 setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logi calTop()));
440 500
441 updateLayerTransform(); 501 updateLayerTransform();
442 502
443 // Update our scroll information if we're overflow:auto/scroll/hidden now th at we know if 503 // Update our scroll information if we're overflow:auto/scroll/hidden now th at we know if
444 // we overflow or not. 504 // we overflow or not.
445 updateScrollInfoAfterLayout(); 505 updateScrollInfoAfterLayout();
446 506
447 // Repaint with our new bounds if they are different from our old bounds. 507 // Repaint with our new bounds if they are different from our old bounds.
448 bool didFullRepaint = repainter.repaintAfterLayout(); 508 bool didFullRepaint = repainter.repaintAfterLayout();
449 if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (sty le()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { 509 if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (sty le()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
450 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 510 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
451 setShouldRepaintOverflowIfNeeded(true); 511 setShouldRepaintOverflowIfNeeded(true);
452 else 512 else
453 repaintOverflow(); 513 repaintOverflow();
454 } 514 }
455 515
516 FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
456 if (textAutosizer) 517 if (textAutosizer)
457 textAutosizer->endLayout(this); 518 textAutosizer->endLayout(this);
458 519
459 clearNeedsLayout(); 520 clearNeedsLayout();
521 delete m_statePusher;
522 m_statePusher = 0;
esprehn 2014/02/15 00:35:43 This should be an OwnPtr you just clear.
460 return true; 523 return true;
461 } 524 }
462 525
463 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom) 526 bool RenderBlockFlow::preLayoutBlockChild(RenderBox* child, bool& skipChildren)
464 { 527 {
465 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); 528 updateBlockChildDirtyBitsBeforeLayout(m_relayoutChildren, child);
466 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); 529
530 if (child->isOutOfFlowPositioned()) {
531 child->containingBlock()->insertPositionedObject(child);
532 adjustPositionedBlock(child, *m_marginInfo);
533 skipChildren = true;
534 return false;
535 }
536
537 if (child->isFloating()) {
538 insertFloatingObject(child);
539 adjustFloatingBlock(*m_marginInfo);
540 skipChildren = true;
541 return false;
542 }
543
544 m_oldPosMarginBefore = maxPositiveMarginBefore();
545 m_oldNegMarginBefore = maxNegativeMarginBefore();
467 546
468 // The child is a normal flow object. Compute the margins we will use for co llapsing now. 547 // The child is a normal flow object. Compute the margins we will use for co llapsing now.
469 child->computeAndSetBlockDirectionMargins(this); 548 child->computeAndSetBlockDirectionMargins(this);
470 549
471 // Try to guess our correct logical top position. In most cases this guess w ill 550 // Try to guess our correct logical top position. In most cases this guess w ill
472 // be correct. Only if we're wrong (when we compute the real logical top pos ition) 551 // be correct. Only if we're wrong (when we compute the real logical top pos ition)
473 // will we have to potentially relayout. 552 // will we have to potentially relayout.
474 LayoutUnit estimateWithoutPagination; 553 m_estimateWithoutPagination = 0;
475 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo , estimateWithoutPagination); 554 m_logicalTopEstimate = estimateLogicalTopPosition(child, *m_marginInfo, m_es timateWithoutPagination);
476 555
477 // Cache our old rect so that we can dirty the proper repaint rects if the c hild moves. 556 // Cache our old rect so that we can dirty the proper repaint rects if the c hild moves.
478 LayoutRect oldRect = child->frameRect(); 557 m_oldRect = child->frameRect();
479 LayoutUnit oldLogicalTop = logicalTopForChild(child); 558 LayoutUnit oldLogicalTop = logicalTopForChild(child);
480 559
481 #if !ASSERT_DISABLED 560 #if !ASSERT_DISABLED
482 LayoutSize oldLayoutDelta = RuntimeEnabledFeatures::repaintAfterLayoutEnable d() ? LayoutSize() : view()->layoutDelta(); 561 m_oldLayoutDelta = RuntimeEnabledFeatures::repaintAfterLayoutEnabled() ? Lay outSize() : view()->layoutDelta();
483 #endif 562 #endif
484 // Go ahead and position the child as though it didn't collapse with the top . 563 // Go ahead and position the child as though it didn't collapse with the top .
485 setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta); 564 setLogicalTopForChild(child, m_logicalTopEstimate, ApplyLayoutDelta);
486 565
487 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child ) : 0; 566 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child ) : 0;
488 RenderBlockFlow* childRenderBlockFlow = (childRenderBlock && child->isRender BlockFlow()) ? toRenderBlockFlow(child) : 0; 567 RenderBlockFlow* childRenderBlockFlow = (childRenderBlock && child->isRender BlockFlow()) ? toRenderBlockFlow(child) : 0;
489 bool markDescendantsWithFloats = false; 568 bool markDescendantsWithFloats = false;
490 if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRe nderBlock && childRenderBlock->containsFloats()) { 569 if (m_logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && child RenderBlock && childRenderBlock->containsFloats()) {
491 markDescendantsWithFloats = true; 570 markDescendantsWithFloats = true;
492 } else if (UNLIKELY(logicalTopEstimate.mightBeSaturated())) { 571 } else if (UNLIKELY(m_logicalTopEstimate.mightBeSaturated())) {
493 // logicalTopEstimate, returned by estimateLogicalTopPosition, might be saturated for 572 // logicalTopEstimate, returned by estimateLogicalTopPosition, might be saturated for
494 // very large elements. If it does the comparison with oldLogicalTop mig ht yield a 573 // very large elements. If it does the comparison with oldLogicalTop mig ht yield a
495 // false negative as adding and removing margins, borders etc from a sat urated number 574 // false negative as adding and removing margins, borders etc from a sat urated number
496 // might yield incorrect results. If this is the case always mark for la yout. 575 // might yield incorrect results. If this is the case always mark for la yout.
497 markDescendantsWithFloats = true; 576 markDescendantsWithFloats = true;
498 } else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) { 577 } else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
499 // If an element might be affected by the presence of floats, then alway s mark it for 578 // If an element might be affected by the presence of floats, then alway s mark it for
500 // layout. 579 // layout.
501 LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom ()); 580 LayoutUnit fb = max(m_previousFloatLogicalBottom, lowestFloatLogicalBott om());
502 if (fb > logicalTopEstimate) 581 if (fb > m_logicalTopEstimate)
503 markDescendantsWithFloats = true; 582 markDescendantsWithFloats = true;
504 } 583 }
505 584
506 if (childRenderBlockFlow) { 585 if (childRenderBlockFlow) {
507 if (markDescendantsWithFloats) 586 if (markDescendantsWithFloats)
508 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout(); 587 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout();
509 if (!child->isWritingModeRoot()) 588 if (!child->isWritingModeRoot())
510 previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogi calTop + childRenderBlockFlow->lowestFloatLogicalBottom()); 589 m_previousFloatLogicalBottom = max(m_previousFloatLogicalBottom, old LogicalTop + childRenderBlockFlow->lowestFloatLogicalBottom());
511 } 590 }
512 591
513 SubtreeLayoutScope layoutScope(child); 592 m_childLayoutScope = new SubtreeLayoutScope(child);
514 if (!child->needsLayout()) 593 if (!child->needsLayout())
515 child->markForPaginationRelayoutIfNeeded(layoutScope); 594 child->markForPaginationRelayoutIfNeeded(*m_childLayoutScope);
516 595
517 bool childHadLayout = child->everHadLayout(); 596 m_childHadLayout = child->everHadLayout();
518 bool childNeededLayout = child->needsLayout(); 597 m_childNeededLayout = child->needsLayout();
esprehn 2014/02/15 00:35:43 This doesn't feel right. Storing so much state in
atreat 2014/02/18 16:03:57 Right, see the comment in the header file. We'll
519 if (childNeededLayout) 598 skipChildren |= !m_childNeededLayout;
520 child->layout(); 599 if (m_childNeededLayout) {
600 if (child->isNonRecursiveLayout())
601 child->preLayout();
602 else
603 child->layout();
604 }
605 return true;
606 }
521 607
522 if (frameView()->partialLayout().isStopping()) 608 void RenderBlockFlow::postLayoutBlockChild(RenderBox* child)
609 {
610 if (child->isOutOfFlowPositioned() || child->isFloating())
523 return; 611 return;
524 612
613 if (m_childNeededLayout && child->isNonRecursiveLayout())
614 child->postLayout();
615
525 // Cache if we are at the top of the block right now. 616 // Cache if we are at the top of the block right now.
526 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock(); 617 bool atBeforeSideOfBlock = m_marginInfo->atBeforeSideOfBlock();
527 618
528 // Now determine the correct ypos based off examination of collapsing margin 619 // Now determine the correct ypos based off examination of collapsing margin
529 // values. 620 // values.
530 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo); 621 LayoutUnit logicalTopBeforeClear = collapseMargins(child, *m_marginInfo);
531 622
532 // Now check for clear. 623 // Now check for clear.
533 LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, old PosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear); 624 LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, *m_marginInfo, m_oldPosMarginBefore, m_oldNegMarginBefore, logicalTopBeforeClear);
534 625
535 bool paginated = view()->layoutState()->isPaginated(); 626 bool paginated = view()->layoutState()->isPaginated();
536 if (paginated) { 627 if (paginated) {
537 logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClea r, estimateWithoutPagination, child, 628 logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClea r, m_estimateWithoutPagination, child,
538 atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear ); 629 atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear );
539 } 630 }
540 631
541 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta); 632 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
542 633
634 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child ) : 0;
635 RenderBlockFlow* childRenderBlockFlow = (childRenderBlock && child->isRender BlockFlow()) ? toRenderBlockFlow(child) : 0;
636
543 // Now we have a final top position. See if it really does end up being diff erent from our estimate. 637 // Now we have a final top position. See if it really does end up being diff erent from our estimate.
544 // clearFloatsIfNeeded can also mark the child as needing a layout even thou gh we didn't move. This happens 638 // clearFloatsIfNeeded can also mark the child as needing a layout even thou gh we didn't move. This happens
545 // when collapseMargins dynamically adds overhanging floats because of a chi ld with negative margins. 639 // when collapseMargins dynamically adds overhanging floats because of a chi ld with negative margins.
546 if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (p aginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow( ))) { 640 if (logicalTopAfterClear != m_logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWido w())) {
547 SubtreeLayoutScope layoutScope(child); 641 SubtreeLayoutScope layoutScope(child);
548 if (child->shrinkToAvoidFloats()) { 642 if (child->shrinkToAvoidFloats()) {
549 // The child's width depends on the line width. 643 // The child's width depends on the line width.
550 // When the child shifts to clear an item, its width can 644 // When the child shifts to clear an item, its width can
551 // change (because it has more available line width). 645 // change (because it has more available line width).
552 // So go ahead and mark the item as dirty. 646 // So go ahead and mark the item as dirty.
553 layoutScope.setChildNeedsLayout(child); 647 layoutScope.setChildNeedsLayout(child);
554 } 648 }
555 649
556 if (childRenderBlock) { 650 if (childRenderBlock) {
557 if (!child->avoidsFloats() && childRenderBlock->containsFloats()) 651 if (!child->avoidsFloats() && childRenderBlock->containsFloats())
558 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout(); 652 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout();
559 if (!child->needsLayout()) 653 if (!child->needsLayout())
560 child->markForPaginationRelayoutIfNeeded(layoutScope); 654 child->markForPaginationRelayoutIfNeeded(layoutScope);
561 } 655 }
562 656
563 // Our guess was wrong. Make the child lay itself out again. 657 // Our guess was wrong. Make the child lay itself out again.
564 child->layoutIfNeeded(); 658 child->layoutIfNeeded();
565 } 659 }
566 660
567 // If we previously encountered a self-collapsing sibling of this child that had clearance then 661 // If we previously encountered a self-collapsing sibling of this child that had clearance then
568 // we set this bit to ensure we would not collapse the child's margins, and those of any subsequent 662 // we set this bit to ensure we would not collapse the child's margins, and those of any subsequent
569 // self-collapsing siblings, with our parent. If this child is not self-coll apsing then it can 663 // self-collapsing siblings, with our parent. If this child is not self-coll apsing then it can
570 // collapse its margins with the parent so reset the bit. 664 // collapse its margins with the parent so reset the bit.
571 if (!marginInfo.canCollapseMarginAfterWithLastChild() && !child->isSelfColla psingBlock()) 665 if (!m_marginInfo->canCollapseMarginAfterWithLastChild() && !child->isSelfCo llapsingBlock())
572 marginInfo.setCanCollapseMarginAfterWithLastChild(true); 666 m_marginInfo->setCanCollapseMarginAfterWithLastChild(true);
573 667
574 // We are no longer at the top of the block if we encounter a non-empty chil d. 668 // We are no longer at the top of the block if we encounter a non-empty chil d.
575 // This has to be done after checking for clear, so that margins can be rese t if a clear occurred. 669 // This has to be done after checking for clear, so that margins can be rese t if a clear occurred.
576 if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock()) 670 if (m_marginInfo->atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
577 marginInfo.setAtBeforeSideOfBlock(false); 671 m_marginInfo->setAtBeforeSideOfBlock(false);
578 672
579 // Now place the child in the correct left position 673 // Now place the child in the correct left position
580 determineLogicalLeftPositionForChild(child, ApplyLayoutDelta); 674 determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
581 675
582 LayoutSize childOffset = child->location() - oldRect.location(); 676 LayoutSize childOffset = child->location() - m_oldRect.location();
583 relayoutShapeDescendantIfMoved(childRenderBlock, childOffset); 677 relayoutShapeDescendantIfMoved(childRenderBlock, childOffset);
584 678
585 // Update our height now that the child has been placed in the correct posit ion. 679 // Update our height now that the child has been placed in the correct posit ion.
586 setLogicalHeight(logicalHeight() + logicalHeightForChild(child)); 680 setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
587 if (mustSeparateMarginAfterForChild(child)) { 681 if (mustSeparateMarginAfterForChild(child)) {
588 setLogicalHeight(logicalHeight() + marginAfterForChild(child)); 682 setLogicalHeight(logicalHeight() + marginAfterForChild(child));
589 marginInfo.clearMargin(); 683 m_marginInfo->clearMargin();
590 } 684 }
591 // If the child has overhanging floats that intrude into following siblings (or possibly out 685 // If the child has overhanging floats that intrude into following siblings (or possibly out
592 // of this block), then the parent gets notified of the floats now. 686 // of this block), then the parent gets notified of the floats now.
593 if (childRenderBlockFlow && childRenderBlockFlow->containsFloats()) 687 if (childRenderBlockFlow && childRenderBlockFlow->containsFloats())
594 maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats( childRenderBlockFlow, !childNeededLayout)); 688 m_maxFloatLogicalBottom = max(m_maxFloatLogicalBottom, addOverhangingFlo ats(childRenderBlockFlow, !m_childNeededLayout));
595 689
596 if (childOffset.width() || childOffset.height()) { 690 if (childOffset.width() || childOffset.height()) {
597 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 691 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
598 view()->addLayoutDelta(childOffset); 692 view()->addLayoutDelta(childOffset);
599 693
600 // If the child moved, we have to repaint it as well as any floating/pos itioned 694 // If the child moved, we have to repaint it as well as any floating/pos itioned
601 // descendants. An exception is if we need a layout. In this case, we kn ow we're going to 695 // descendants. An exception is if we need a layout. In this case, we kn ow we're going to
602 // repaint ourselves (and the child) anyway. 696 // repaint ourselves (and the child) anyway.
603 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && childHadLayou t && !selfNeedsLayout()) 697 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && m_childHadLay out && !selfNeedsLayout())
604 child->repaintOverhangingFloats(true); 698 child->repaintOverhangingFloats(true);
605 else if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintD uringLayout()) 699 else if (m_childHadLayout && !selfNeedsLayout() && child->checkForRepain tDuringLayout())
606 child->repaintDuringLayoutIfMoved(oldRect); 700 child->repaintDuringLayoutIfMoved(m_oldRect);
607 } 701 }
608 702
609 if (!childHadLayout && child->checkForRepaint()) { 703 if (!m_childHadLayout && child->checkForRepaint()) {
610 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 704 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
611 child->repaint(); 705 child->repaint();
612 child->repaintOverhangingFloats(true); 706 child->repaintOverhangingFloats(true);
613 } 707 }
614 708
615 if (paginated) { 709 if (paginated) {
616 // Check for an after page/column break. 710 // Check for an after page/column break.
617 LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInf o); 711 LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), *m_margin Info);
618 if (newHeight != height()) 712 if (newHeight != height())
619 setLogicalHeight(newHeight); 713 setLogicalHeight(newHeight);
620 } 714 }
621 715
622 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) { 716 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) {
623 ASSERT(view()->layoutDeltaMatches(oldLayoutDelta)); 717 ASSERT(view()->layoutDeltaMatches(m_oldLayoutDelta));
624 } 718 }
719
720 m_lastNormalFlowChild = child;
721 delete m_childLayoutScope;
722 m_childLayoutScope = 0;
625 } 723 }
626 724
627 LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopA fterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBefore SideOfBlock) 725 LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopA fterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBefore SideOfBlock)
628 { 726 {
629 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child ) : 0; 727 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child ) : 0;
630 728
631 if (estimateWithoutPagination != logicalTopAfterClear) { 729 if (estimateWithoutPagination != logicalTopAfterClear) {
632 // Our guess prior to pagination movement was wrong. Before we attempt t o paginate, let's try again at the new 730 // Our guess prior to pagination movement was wrong. Before we attempt t o paginate, let's try again at the new
633 // position. 731 // position.
634 setLogicalHeight(logicalTopAfterClear); 732 setLogicalHeight(logicalTopAfterClear);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set( ); 939 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set( );
842 FloatingObjectSetIterator end = floatingObjectSet.end(); 940 FloatingObjectSetIterator end = floatingObjectSet.end();
843 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it) 941 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it)
844 oldIntrudingFloatSet.remove((*it)->renderer()); 942 oldIntrudingFloatSet.remove((*it)->renderer());
845 if (!oldIntrudingFloatSet.isEmpty()) 943 if (!oldIntrudingFloatSet.isEmpty())
846 markAllDescendantsWithFloatsForLayout(); 944 markAllDescendantsWithFloatsForLayout();
847 } 945 }
848 } 946 }
849 } 947 }
850 948
851 void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max FloatLogicalBottom, SubtreeLayoutScope& layoutScope, LayoutUnit beforeEdge, Layo utUnit afterEdge) 949 void RenderBlockFlow::layoutBlockChildren(LayoutUnit beforeEdge, LayoutUnit afte rEdge, bool traverseChildren)
852 { 950 {
853 dirtyForLayoutFromPercentageHeightDescendants(layoutScope);
854
855 // Lay out our hypothetical grid line as though it occurs at the top of the block.
856 if (view()->layoutState()->lineGrid() == this)
857 layoutLineGridBox();
858
859 // The margin struct caches all our current margin collapsing state. The com pact struct caches state when we encounter compacts, 951 // The margin struct caches all our current margin collapsing state. The com pact struct caches state when we encounter compacts,
860 MarginInfo marginInfo(this, beforeEdge, afterEdge); 952 m_marginInfo = new MarginInfo(this, beforeEdge, afterEdge);
esprehn 2014/02/15 00:35:43 Adding more mallocs doesn't seem like the right wa
861 953
862 // Fieldsets need to find their legend and position it inside the border of the object. 954 // Fieldsets need to find their legend and position it inside the border of the object.
863 // The legend then gets skipped during normal layout. The same is true for r uby text. 955 // The legend then gets skipped during normal layout. The same is true for r uby text.
864 // It doesn't get included in the normal layout process but is instead skipp ed. 956 // It doesn't get included in the normal layout process but is instead skipp ed.
865 RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren, layoutScope); 957 m_childToExclude = layoutSpecialExcludedChild(m_relayoutChildren, *m_layoutS cope);
958 m_previousFloatLogicalBottom = 0;
959 m_maxFloatLogicalBottom = 0;
960 m_lastNormalFlowChild = 0;
866 961
867 LayoutUnit previousFloatLogicalBottom = 0; 962 if (!traverseChildren)
868 maxFloatLogicalBottom = 0; 963 return;
869 964
870 RenderBox* next = firstChildBox(); 965 bool skippingChildren = false;
871 RenderBox* lastNormalFlowChild = 0; 966 #if NON_RECURSIVE
967 Order order = Pre;
968 RenderObject* childObject = nextForLayout(order, this, skippingChildren);
969 for (; childObject && childObject != this; childObject = childObject->nextFo rLayout(order, this, skippingChildren)) {
970 if (!childObject->isBox())
971 continue;
972 RenderBox *child = toRenderBox(childObject);
973 skippingChildren = child->childrenInline();
974 #else
975 (void)skippingChildren;
976 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBo x()) {
977 #endif
872 978
873 while (next) { 979 ASSERT(child->parent()->isRenderBlockFlow());
874 RenderBox* child = next; 980 RenderBlockFlow* directParent = toRenderBlockFlow(child->parent());
875 next = child->nextSiblingBox();
876 981
877 LayoutRectRecorder recorder(*child); 982 LayoutRectRecorder recorder(*child);
878 983 if (directParent->m_childToExclude == child) {
879 if (childToExclude == child) 984 skippingChildren = true;
880 continue; // Skip this child, since it will be positioned by the spe cialized subclass (fieldsets and ruby runs). 985 continue; // Skip this child, since it will be positioned by the spe cialized subclass (fieldsets and ruby runs).
881
882 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
883
884 if (child->isOutOfFlowPositioned()) {
885 child->containingBlock()->insertPositionedObject(child);
886 adjustPositionedBlock(child, marginInfo);
887 continue;
888 }
889 if (child->isFloating()) {
890 insertFloatingObject(child);
891 adjustFloatingBlock(marginInfo);
892 continue;
893 } 986 }
894 987
988 #if NON_RECURSIVE
989 if (order == Pre) {
990 #endif
991
895 // Lay out the child. 992 // Lay out the child.
896 layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloat LogicalBottom); 993 if (!directParent->preLayoutBlockChild(child, skippingChildren))
897 lastNormalFlowChild = child; 994 continue;
995
996 #if NON_RECURSIVE
997 } else {
998 #endif
999
1000 directParent->postLayoutBlockChild(child);
1001
1002 #if NON_RECURSIVE
1003 }
1004 #endif
898 1005
899 // If doing a partial layout and the child was the target renderer, earl y exit here. 1006 // If doing a partial layout and the child was the target renderer, earl y exit here.
900 if (frameView()->partialLayout().checkPartialLayoutComplete(child)) 1007 if (frameView()->partialLayout().checkPartialLayoutComplete(child))
901 return; 1008 return;
902
903 } 1009 }
904
905 // Now do the handling of the bottom of the block, adding in our bottom bord er/padding and
906 // determining the correct collapsed bottom margin information.
907 handleAfterSideOfBlock(lastNormalFlowChild, beforeEdge, afterEdge, marginInf o);
908 } 1010 }
909 1011
910 // Our MarginInfo state used when laying out block children. 1012 // Our MarginInfo state used when laying out block children.
911 MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPaddin g, LayoutUnit afterBorderPadding) 1013 MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPaddin g, LayoutUnit afterBorderPadding)
912 : m_canCollapseMarginAfterWithLastChild(true) 1014 : m_canCollapseMarginAfterWithLastChild(true)
913 , m_atBeforeSideOfBlock(true) 1015 , m_atBeforeSideOfBlock(true)
914 , m_atAfterSideOfBlock(false) 1016 , m_atAfterSideOfBlock(false)
915 , m_hasMarginBeforeQuirk(false) 1017 , m_hasMarginBeforeQuirk(false)
916 , m_hasMarginAfterQuirk(false) 1018 , m_hasMarginAfterQuirk(false)
917 , m_determinedMarginBeforeQuirk(false) 1019 , m_determinedMarginBeforeQuirk(false)
(...skipping 1958 matching lines...) Expand 10 before | Expand all | Expand 10 after
2876 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() 2978 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData()
2877 { 2979 {
2878 if (m_rareData) 2980 if (m_rareData)
2879 return *m_rareData; 2981 return *m_rareData;
2880 2982
2881 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 2983 m_rareData = adoptPtr(new RenderBlockFlowRareData(this));
2882 return *m_rareData; 2984 return *m_rareData;
2883 } 2985 }
2884 2986
2885 } // namespace WebCore 2987 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698