OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. |
5 * | 5 * |
6 * Other contributors: | 6 * Other contributors: |
7 * Robert O'Callahan <roc+@cs.cmu.edu> | 7 * Robert O'Callahan <roc+@cs.cmu.edu> |
8 * David Baron <dbaron@fas.harvard.edu> | 8 * David Baron <dbaron@fas.harvard.edu> |
9 * Christian Biesinger <cbiesinger@web.de> | 9 * Christian Biesinger <cbiesinger@web.de> |
10 * Randall Jesup <rjesup@wgate.com> | 10 * Randall Jesup <rjesup@wgate.com> |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
142 RenderLayer::RenderLayer(RenderLayerModelObject* renderer) | 142 RenderLayer::RenderLayer(RenderLayerModelObject* renderer) |
143 : m_inResizeMode(false) | 143 : m_inResizeMode(false) |
144 , m_scrollDimensionsDirty(true) | 144 , m_scrollDimensionsDirty(true) |
145 , m_normalFlowListDirty(true) | 145 , m_normalFlowListDirty(true) |
146 , m_hasSelfPaintingLayerDescendant(false) | 146 , m_hasSelfPaintingLayerDescendant(false) |
147 , m_hasSelfPaintingLayerDescendantDirty(false) | 147 , m_hasSelfPaintingLayerDescendantDirty(false) |
148 , m_hasOutOfFlowPositionedDescendant(false) | 148 , m_hasOutOfFlowPositionedDescendant(false) |
149 , m_hasOutOfFlowPositionedDescendantDirty(true) | 149 , m_hasOutOfFlowPositionedDescendantDirty(true) |
150 , m_hasUnclippedDescendant(false) | 150 , m_hasUnclippedDescendant(false) |
151 , m_needsCompositedScrolling(false) | 151 , m_needsCompositedScrolling(false) |
152 , m_descendantsAreContiguousInStackingOrder(false) | 152 , m_canBePromotedToStackingContainer(false) |
153 , m_descendantsAreContiguousInStackingOrderDirty(true) | 153 , m_canBePromotedToStackingContainerDirty(true) |
154 , m_isRootLayer(renderer->isRenderView()) | 154 , m_isRootLayer(renderer->isRenderView()) |
155 , m_usedTransparency(false) | 155 , m_usedTransparency(false) |
156 , m_paintingInsideReflection(false) | 156 , m_paintingInsideReflection(false) |
157 , m_inOverflowRelayout(false) | 157 , m_inOverflowRelayout(false) |
158 , m_repaintStatus(NeedsNormalRepaint) | 158 , m_repaintStatus(NeedsNormalRepaint) |
159 , m_visibleContentStatusDirty(true) | 159 , m_visibleContentStatusDirty(true) |
160 , m_hasVisibleContent(false) | 160 , m_hasVisibleContent(false) |
161 , m_visibleDescendantStatusDirty(false) | 161 , m_visibleDescendantStatusDirty(false) |
162 , m_hasVisibleDescendant(false) | 162 , m_hasVisibleDescendant(false) |
163 , m_isPaginated(false) | 163 , m_isPaginated(false) |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
513 } | 513 } |
514 } | 514 } |
515 | 515 |
516 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const | 516 bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const |
517 { | 517 { |
518 return renderer()->frame() | 518 return renderer()->frame() |
519 && renderer()->frame()->page()->settings() | 519 && renderer()->frame()->page()->settings() |
520 && (renderer()->frame()->page()->settings()->acceleratedCompositingForOv erflowScrollEnabled() != AcceleratedCompositingForOverflowScrollDisabled); | 520 && (renderer()->frame()->page()->settings()->acceleratedCompositingForOv erflowScrollEnabled() != AcceleratedCompositingForOverflowScrollDisabled); |
521 } | 521 } |
522 | 522 |
523 // If we are a stacking container, then this function will determine if our | 523 // Determine whether the current layer can be promoted to a stacking container. |
524 // descendants for a contiguous block in stacking order. This is required in | 524 // We do this by computing what positive and negative z-order lists would look |
525 // order for an element to be safely promoted to a stacking container. It is saf e | 525 // like before and after promotion, and ensuring that proper stacking order is |
526 // to become a stacking container if this change would not alter the stacking | 526 // preserved between the two sets of lists. |
527 // order of layers on the page. That can only happen if a non-descendant appear | 527 void RenderLayer::updateCanBeStackingContainer() |
528 // between us and our descendants in stacking order. Here's an example: | |
529 // | |
530 // this | |
531 // / | \. | |
532 // A B C | |
533 // /\ | /\. | |
534 // 0 -8 D 2 7 | |
535 // | | |
536 // 5 | |
537 // | |
538 // I've labeled our normal flow descendants A, B, C, and D, our stacking | |
539 // container descendants with their z indices, and us with 'this' (we're a | |
540 // stacking container and our zIndex doesn't matter here). These nodes appear in | |
541 // three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal | |
542 // flow layers don't overlap). So if we arrange these lists in order we get our | |
543 // stacking order: | |
544 // | |
545 // [-8], [A-D], [0, 2, 5, 7]--> pos z-order. | |
546 // | | | |
547 // Neg z-order. <-+ +--> Normal flow descendants. | |
548 // | |
549 // We can then assign new, 'stacking' order indices to these elements as follows : | |
550 // | |
551 // [-8], [A-D], [0, 2, 5, 7] | |
552 // 'Stacking' indices: -1 0 1 2 3 4 | |
553 // | |
554 // Note that the normal flow descendants can share an index because they don't | |
555 // stack/overlap. Now our problem becomes very simple: a layer can safely become | |
556 // a stacking container if the stacking-order indices of it and its descendants | |
557 // appear in a contiguous block in the list of stacking indices. This problem | |
558 // can be solved very efficiently by calculating the min/max stacking indices in | |
559 // the subtree, and the number stacking container descendants. Once we have this | |
560 // information, we know that the subtree's indices form a contiguous block if: | |
561 // | |
562 // maxStackIndex - minStackIndex == numSCDescendants | |
563 // | |
564 // So for node A in the example above we would have: | |
565 // maxStackIndex = 1 | |
566 // minStackIndex = -1 | |
567 // numSCDecendants = 2 | |
568 // | |
569 // and so, | |
570 // maxStackIndex - minStackIndex == numSCDescendants | |
571 // ===> 1 - (-1) == 2 | |
572 // ===> 2 == 2 | |
573 // | |
574 // Since this is true, A can safely become a stacking container. | |
575 // Now, for node C we have: | |
576 // | |
577 // maxStackIndex = 4 | |
578 // minStackIndex = 0 <-- because C has stacking index 0. | |
579 // numSCDecendants = 2 | |
580 // | |
581 // and so, | |
582 // maxStackIndex - minStackIndex == numSCDescendants | |
583 // ===> 4 - 0 == 2 | |
584 // ===> 4 == 2 | |
585 // | |
586 // Since this is false, C cannot be safely promoted to a stacking container. Thi s | |
587 // happened because of the elements with z-index 5 and 0. Now if 5 had been a | |
588 // child of C rather than D, and A had no child with Z index 0, we would have ha d: | |
589 // | |
590 // maxStackIndex = 3 | |
591 // minStackIndex = 0 <-- because C has stacking index 0. | |
592 // numSCDecendants = 3 | |
593 // | |
594 // and so, | |
595 // maxStackIndex - minStackIndex == numSCDescendants | |
596 // ===> 3 - 0 == 3 | |
597 // ===> 3 == 3 | |
598 // | |
599 // And we would conclude that C could be promoted. | |
600 void RenderLayer::updateDescendantsAreContiguousInStackingOrder() | |
601 { | 528 { |
602 if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext() || acceleratedCompositingForOverflowScrollEnabled() == AcceleratedCompositingFor OverflowScrollDisabled) | 529 TRACE_EVENT0("blink_rendering", "RenderLayer::updateCanBeStackingContainer") ; |
530 | |
531 if (isStackingContext() || !m_canBePromotedToStackingContainerDirty || !acce leratedCompositingForOverflowScrollEnabled()) | |
603 return; | 532 return; |
604 | 533 |
605 OwnPtr<Vector<RenderLayer*> > posZOrderList; | 534 FrameView* frameView = renderer()->view()->frameView(); |
606 OwnPtr<Vector<RenderLayer*> > negZOrderList; | 535 if (!frameView || !frameView->containsScrollableArea(this)) |
607 rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList); | 536 return; |
608 | 537 |
609 // Create a reverse lookup. | 538 RenderLayer* ancestorStackingContext = this->ancestorStackingContext(); |
610 HashMap<const RenderLayer*, int> lookup; | 539 if (!ancestorStackingContext) |
540 return; | |
611 | 541 |
612 if (negZOrderList) { | 542 OwnPtr<Vector<RenderLayer*> > posZOrderListBeforePromote = adoptPtr(new Vect or<RenderLayer*>); |
613 int stackingOrderIndex = -1; | 543 OwnPtr<Vector<RenderLayer*> > negZOrderListBeforePromote = adoptPtr(new Vect or<RenderLayer*>); |
614 size_t listSize = negZOrderList->size(); | 544 OwnPtr<Vector<RenderLayer*> > posZOrderListAfterPromote = adoptPtr(new Vecto r<RenderLayer*>); |
615 for (size_t i = 0; i < listSize; ++i) { | 545 OwnPtr<Vector<RenderLayer*> > negZOrderListAfterPromote = adoptPtr(new Vecto r<RenderLayer*>); |
616 RenderLayer* currentLayer = negZOrderList->at(listSize - i - 1); | 546 |
617 if (!currentLayer->isStackingContext()) | 547 collectBeforePromotionZOrderList(ancestorStackingContext, posZOrderListBefor ePromote, negZOrderListBeforePromote); |
618 continue; | 548 collectAfterPromotionZOrderList(ancestorStackingContext, posZOrderListAfterP romote, negZOrderListAfterPromote); |
619 lookup.set(currentLayer, stackingOrderIndex--); | 549 |
620 } | 550 size_t maxIndex = std::min(posZOrderListAfterPromote->size() + negZOrderList AfterPromote->size(), posZOrderListBeforePromote->size() + negZOrderListBeforePr omote->size()); |
551 | |
552 m_canBePromotedToStackingContainerDirty = false; | |
553 m_canBePromotedToStackingContainer = false; | |
554 | |
555 for (size_t i = 0; i < maxIndex; ++i) { | |
556 const RenderLayer* layerBeforePromote = i < negZOrderListBeforePromote-> size() | |
557 ? negZOrderListBeforePromote->at(i) | |
558 : posZOrderListBeforePromote->at(i - negZOrderListBeforePromote->siz e()); | |
559 const RenderLayer* layerAfterPromote = i < negZOrderListAfterPromote->si ze() | |
560 ? negZOrderListAfterPromote->at(i) | |
561 : posZOrderListAfterPromote->at(i - negZOrderListAfterPromote->size( )); | |
562 | |
563 if (layerBeforePromote != layerAfterPromote && (layerAfterPromote != thi s || renderer()->hasBackground())) | |
564 return; | |
565 | |
566 if (layerAfterPromote == this) | |
567 break; | |
esprehn
2013/05/15 06:50:18
This should be in the loop condition like i < maxI
hartmanng
2013/05/15 15:18:59
Done.
| |
621 } | 568 } |
622 | 569 |
623 if (posZOrderList) { | 570 for (size_t i = 0; i < maxIndex; ++i) { |
624 size_t listSize = posZOrderList->size(); | 571 const RenderLayer* layerBeforePromote = i < posZOrderListBeforePromote-> size() |
625 int stackingOrderIndex = 1; | 572 ? posZOrderListBeforePromote->at(posZOrderListBeforePromote->size() - i - 1) |
esprehn
2013/05/15 06:50:18
This kind of math is really scary. I guess we do b
hartmanng
2013/05/15 15:18:59
Yeah I know what you mean - can you think of a way
| |
626 for (size_t i = 0; i < listSize; ++i) { | 573 : negZOrderListBeforePromote->at(negZOrderListBeforePromote->size() + posZOrderListBeforePromote->size() - i - 1); |
627 RenderLayer* currentLayer = posZOrderList->at(i); | 574 const RenderLayer* layerAfterPromote = i < posZOrderListAfterPromote->si ze() |
628 if (!currentLayer->isStackingContext()) | 575 ? posZOrderListAfterPromote->at(posZOrderListAfterPromote->size() - i - 1) |
629 continue; | 576 : negZOrderListAfterPromote->at(negZOrderListAfterPromote->size() + posZOrderListAfterPromote->size() - i - 1); |
630 lookup.set(currentLayer, stackingOrderIndex++); | 577 |
631 } | 578 if (layerBeforePromote != layerAfterPromote && layerAfterPromote != this ) |
579 return; | |
580 | |
581 if (layerAfterPromote == this) | |
582 break; | |
esprehn
2013/05/15 06:50:18
Same deal
hartmanng
2013/05/15 15:18:59
Done.
| |
632 } | 583 } |
633 | 584 |
634 int minIndex = 0; | 585 m_canBePromotedToStackingContainer = true; |
635 int maxIndex = 0; | |
636 int count = 0; | |
637 bool firstIteration = true; | |
638 updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, max Index, count, firstIteration); | |
639 | |
640 m_descendantsAreContiguousInStackingOrderDirty = false; | |
641 } | |
642 | |
643 void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const H ashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& coun t, bool firstIteration) | |
644 { | |
645 if (isStackingContext() && !firstIteration) { | |
646 if (lookup.contains(this)) { | |
647 minIndex = std::min(minIndex, lookup.get(this)); | |
648 maxIndex = std::max(maxIndex, lookup.get(this)); | |
649 count++; | |
650 } | |
651 return; | |
652 } | |
653 | |
654 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) { | |
655 int childMinIndex = 0; | |
656 int childMaxIndex = 0; | |
657 int childCount = 0; | |
658 child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, ch ildMinIndex, childMaxIndex, childCount, false); | |
659 if (childCount) { | |
660 count += childCount; | |
661 minIndex = std::min(minIndex, childMinIndex); | |
662 maxIndex = std::max(maxIndex, childMaxIndex); | |
663 } | |
664 } | |
665 | |
666 if (!isStackingContext()) { | |
667 m_descendantsAreContiguousInStackingOrder = (maxIndex - minIndex) == cou nt; | |
668 m_descendantsAreContiguousInStackingOrderDirty = false; | |
669 } | |
670 } | 586 } |
671 | 587 |
672 static inline bool isPositionedContainer(const RenderLayer* layer) | 588 static inline bool isPositionedContainer(const RenderLayer* layer) |
673 { | 589 { |
674 // FIXME: This is not in sync with containingBlock. | 590 // FIXME: This is not in sync with containingBlock. |
675 // RenderObject::canContainFixedPositionedObject() should probably be used | 591 // RenderObject::canContainFixedPositionedObject() should probably be used |
676 // instead. | 592 // instead. |
677 RenderLayerModelObject* layerRenderer = layer->renderer(); | 593 RenderLayerModelObject* layerRenderer = layer->renderer(); |
678 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr ansform(); | 594 return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTr ansform(); |
679 } | 595 } |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1093 if (curr == ancestorStackingContainer) | 1009 if (curr == ancestorStackingContainer) |
1094 return; | 1010 return; |
1095 } | 1011 } |
1096 } | 1012 } |
1097 | 1013 |
1098 bool RenderLayer::canBeStackingContainer() const | 1014 bool RenderLayer::canBeStackingContainer() const |
1099 { | 1015 { |
1100 if (isStackingContext() || !ancestorStackingContainer()) | 1016 if (isStackingContext() || !ancestorStackingContainer()) |
1101 return true; | 1017 return true; |
1102 | 1018 |
1103 ASSERT(!m_descendantsAreContiguousInStackingOrderDirty); | 1019 ASSERT(!m_canBePromotedToStackingContainerDirty); |
1104 return m_descendantsAreContiguousInStackingOrder; | 1020 return m_canBePromotedToStackingContainer; |
1105 } | 1021 } |
1106 | 1022 |
1107 void RenderLayer::setHasVisibleContent() | 1023 void RenderLayer::setHasVisibleContent() |
1108 { | 1024 { |
1109 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { | 1025 if (m_hasVisibleContent && !m_visibleContentStatusDirty) { |
1110 ASSERT(!parent() || parent()->hasVisibleDescendant()); | 1026 ASSERT(!parent() || parent()->hasVisibleDescendant()); |
1111 return; | 1027 return; |
1112 } | 1028 } |
1113 | 1029 |
1114 m_visibleContentStatusDirty = false; | 1030 m_visibleContentStatusDirty = false; |
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2090 case AcceleratedCompositingForOverflowScrollAlwaysOn: | 2006 case AcceleratedCompositingForOverflowScrollAlwaysOn: |
2091 return true; | 2007 return true; |
2092 } | 2008 } |
2093 | 2009 |
2094 ASSERT_NOT_REACHED(); | 2010 ASSERT_NOT_REACHED(); |
2095 return m_needsCompositedScrolling; | 2011 return m_needsCompositedScrolling; |
2096 } | 2012 } |
2097 | 2013 |
2098 void RenderLayer::updateNeedsCompositedScrolling() | 2014 void RenderLayer::updateNeedsCompositedScrolling() |
2099 { | 2015 { |
2100 if (RenderLayer* ancestor = ancestorStackingContext()) | 2016 updateCanBeStackingContainer(); |
2101 ancestor->updateDescendantsAreContiguousInStackingOrder(); | |
2102 | 2017 |
2103 bool needsCompositedScrolling = false; | 2018 bool needsCompositedScrolling = false; |
2019 updateDescendantDependentFlags(); | |
2104 | 2020 |
2105 FrameView* frameView = renderer()->view()->frameView(); | 2021 ASSERT(renderer()->view()->frameView() && renderer()->view()->frameView()->c ontainsScrollableArea(this)); |
2106 if (frameView && frameView->containsScrollableArea(this)) { | 2022 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEn abled() |
2107 updateDescendantDependentFlags(); | 2023 && canBeStackingContainer() |
2108 | 2024 && !hasUnclippedDescendant(); |
2109 bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScro llEnabled() | |
2110 && canBeStackingContainer() | |
2111 && !hasUnclippedDescendant(); | |
2112 | 2025 |
2113 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) | 2026 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING) |
2114 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->st yle()->useTouchOverflowScrolling(); | 2027 needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style( )->useTouchOverflowScrolling(); |
2115 #else | 2028 #else |
2116 needsCompositedScrolling = forceUseCompositedScrolling; | 2029 needsCompositedScrolling = forceUseCompositedScrolling; |
2117 #endif | 2030 #endif |
2118 // We gather a boolean value for use with Google UMA histograms to | 2031 // We gather a boolean value for use with Google UMA histograms to |
2119 // quantify the actual effects of a set of patches attempting to | 2032 // quantify the actual effects of a set of patches attempting to |
2120 // relax composited scrolling requirements, thereby increasing the | 2033 // relax composited scrolling requirements, thereby increasing the |
2121 // number of composited overflow divs. | 2034 // number of composited overflow divs. |
2122 if (acceleratedCompositingForOverflowScrollEnabled()) | 2035 if (acceleratedCompositingForOverflowScrollEnabled()) |
2123 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScro lling", needsCompositedScrolling, 2); | 2036 HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrollin g", needsCompositedScrolling, 2); |
2124 } | |
2125 | 2037 |
2126 setNeedsCompositedScrolling(needsCompositedScrolling); | 2038 setNeedsCompositedScrolling(needsCompositedScrolling); |
2127 } | 2039 } |
2128 | 2040 |
2129 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling) | 2041 void RenderLayer::setNeedsCompositedScrolling(bool needsCompositedScrolling) |
2130 { | 2042 { |
2131 if (m_needsCompositedScrolling == needsCompositedScrolling) | 2043 if (m_needsCompositedScrolling == needsCompositedScrolling) |
2132 return; | 2044 return; |
2133 | 2045 |
2134 m_needsCompositedScrolling = needsCompositedScrolling; | 2046 m_needsCompositedScrolling = needsCompositedScrolling; |
(...skipping 3519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5654 { | 5566 { |
5655 ASSERT(m_layerListMutationAllowed); | 5567 ASSERT(m_layerListMutationAllowed); |
5656 ASSERT(isStackingContainer()); | 5568 ASSERT(isStackingContainer()); |
5657 | 5569 |
5658 if (m_posZOrderList) | 5570 if (m_posZOrderList) |
5659 m_posZOrderList->clear(); | 5571 m_posZOrderList->clear(); |
5660 if (m_negZOrderList) | 5572 if (m_negZOrderList) |
5661 m_negZOrderList->clear(); | 5573 m_negZOrderList->clear(); |
5662 m_zOrderListsDirty = true; | 5574 m_zOrderListsDirty = true; |
5663 | 5575 |
5664 m_descendantsAreContiguousInStackingOrderDirty = true; | 5576 m_canBePromotedToStackingContainerDirty = true; |
5665 | 5577 |
5666 if (!renderer()->documentBeingDestroyed()) { | 5578 if (!renderer()->documentBeingDestroyed()) { |
5667 compositor()->setNeedsUpdateCompositedScrolling(); | 5579 compositor()->setNeedsUpdateCompositedScrolling(); |
5668 compositor()->setCompositingLayersNeedRebuild(); | 5580 compositor()->setCompositingLayersNeedRebuild(); |
5669 if (acceleratedCompositingForOverflowScrollEnabled()) | 5581 if (acceleratedCompositingForOverflowScrollEnabled()) |
5670 compositor()->setShouldReevaluateCompositingAfterLayout(); | 5582 compositor()->setShouldReevaluateCompositingAfterLayout(); |
5671 } | 5583 } |
5672 } | 5584 } |
5673 | 5585 |
5674 void RenderLayer::dirtyStackingContainerZOrderLists() | 5586 void RenderLayer::dirtyStackingContainerZOrderLists() |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6497 } | 6409 } |
6498 } | 6410 } |
6499 | 6411 |
6500 void showLayerTree(const WebCore::RenderObject* renderer) | 6412 void showLayerTree(const WebCore::RenderObject* renderer) |
6501 { | 6413 { |
6502 if (!renderer) | 6414 if (!renderer) |
6503 return; | 6415 return; |
6504 showLayerTree(renderer->enclosingLayer()); | 6416 showLayerTree(renderer->enclosingLayer()); |
6505 } | 6417 } |
6506 #endif | 6418 #endif |
OLD | NEW |