| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) | 5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserv
ed. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserv
ed. |
| 7 * Copyright (C) 2009 Google Inc. All rights reserved. | 7 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 8 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 8 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 , m_node(node) | 249 , m_node(node) |
| 250 , m_parent(nullptr) | 250 , m_parent(nullptr) |
| 251 , m_previous(nullptr) | 251 , m_previous(nullptr) |
| 252 , m_next(nullptr) | 252 , m_next(nullptr) |
| 253 #if ENABLE(ASSERT) | 253 #if ENABLE(ASSERT) |
| 254 , m_hasAXObject(false) | 254 , m_hasAXObject(false) |
| 255 , m_setNeedsLayoutForbidden(false) | 255 , m_setNeedsLayoutForbidden(false) |
| 256 #endif | 256 #endif |
| 257 , m_bitfields(node) | 257 , m_bitfields(node) |
| 258 { | 258 { |
| 259 // TODO(wangxianzhu): Move this into initialization list when we enable the
feature by default. | |
| 260 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) | |
| 261 m_previousPositionFromPaintInvalidationBacking = uninitializedPaintOffse
t(); | |
| 262 | |
| 263 #ifndef NDEBUG | 259 #ifndef NDEBUG |
| 264 layoutObjectCounter().increment(); | 260 layoutObjectCounter().increment(); |
| 265 #endif | 261 #endif |
| 266 InstanceCounters::incrementCounter(InstanceCounters::LayoutObjectCounter); | 262 InstanceCounters::incrementCounter(InstanceCounters::LayoutObjectCounter); |
| 267 } | 263 } |
| 268 | 264 |
| 269 LayoutObject::~LayoutObject() | 265 LayoutObject::~LayoutObject() |
| 270 { | 266 { |
| 271 ASSERT(!m_hasAXObject); | 267 ASSERT(!m_hasAXObject); |
| 272 #ifndef NDEBUG | 268 #ifndef NDEBUG |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1210 paintRect.intersect(frameView->visibleContentRect()); | 1206 paintRect.intersect(frameView->visibleContentRect()); |
| 1211 if (paintRect.isEmpty()) | 1207 if (paintRect.isEmpty()) |
| 1212 return; | 1208 return; |
| 1213 | 1209 |
| 1214 if (HostWindow* window = frameView->getHostWindow()) | 1210 if (HostWindow* window = frameView->getHostWindow()) |
| 1215 window->invalidateRect(frameView->contentsToRootFrame(paintRect)); | 1211 window->invalidateRect(frameView->contentsToRootFrame(paintRect)); |
| 1216 } | 1212 } |
| 1217 | 1213 |
| 1218 void LayoutObject::invalidatePaintUsingContainer(const LayoutBoxModelObject& pai
ntInvalidationContainer, const LayoutRect& dirtyRect, PaintInvalidationReason in
validationReason) const | 1214 void LayoutObject::invalidatePaintUsingContainer(const LayoutBoxModelObject& pai
ntInvalidationContainer, const LayoutRect& dirtyRect, PaintInvalidationReason in
validationReason) const |
| 1219 { | 1215 { |
| 1220 // TODO(wangxianzhu): Enable the following assert after paint invalidation f
or spv2 is ready. | |
| 1221 // ASSERT(!RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 1222 | |
| 1223 if (paintInvalidationContainer.frameView()->shouldThrottleRendering()) | 1216 if (paintInvalidationContainer.frameView()->shouldThrottleRendering()) |
| 1224 return; | 1217 return; |
| 1225 | 1218 |
| 1226 ASSERT(gDisablePaintInvalidationStateAsserts || document().lifecycle().state
() == DocumentLifecycle::InPaintInvalidation); | 1219 ASSERT(gDisablePaintInvalidationStateAsserts |
| 1220 || document().lifecycle().state() == DocumentLifecycle::InPaintInvalidat
ion |
| 1221 || (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() && docume
nt().lifecycle().state() == DocumentLifecycle::InPrePaintTreeWalk)); |
| 1227 | 1222 |
| 1228 if (dirtyRect.isEmpty()) | 1223 if (dirtyRect.isEmpty()) |
| 1229 return; | 1224 return; |
| 1230 | 1225 |
| 1231 RELEASE_ASSERT(isRooted()); | 1226 RELEASE_ASSERT(isRooted()); |
| 1232 | 1227 |
| 1233 // FIXME: Unify "devtools.timeline.invalidationTracking" and "blink.invalida
tion". crbug.com/413527. | 1228 // FIXME: Unify "devtools.timeline.invalidationTracking" and "blink.invalida
tion". crbug.com/413527. |
| 1234 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidati
onTracking"), | 1229 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidati
onTracking"), |
| 1235 "PaintInvalidationTracking", | 1230 "PaintInvalidationTracking", |
| 1236 TRACE_EVENT_SCOPE_THREAD, | 1231 TRACE_EVENT_SCOPE_THREAD, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 invalidateDisplayItemClients(*paintInvalidationContainer, PaintInvalidat
ionRectangle); | 1320 invalidateDisplayItemClients(*paintInvalidationContainer, PaintInvalidat
ionRectangle); |
| 1326 } | 1321 } |
| 1327 | 1322 |
| 1328 void LayoutObject::invalidatePaintRectangleNotInvalidatingDisplayItemClients(con
st LayoutRect& r) const | 1323 void LayoutObject::invalidatePaintRectangleNotInvalidatingDisplayItemClients(con
st LayoutRect& r) const |
| 1329 { | 1324 { |
| 1330 invalidatePaintRectangleInternal(r); | 1325 invalidatePaintRectangleInternal(r); |
| 1331 } | 1326 } |
| 1332 | 1327 |
| 1333 void LayoutObject::invalidateTreeIfNeeded(PaintInvalidationState& paintInvalidat
ionState) | 1328 void LayoutObject::invalidateTreeIfNeeded(PaintInvalidationState& paintInvalidat
ionState) |
| 1334 { | 1329 { |
| 1330 ASSERT(!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()); |
| 1335 ASSERT(!needsLayout()); | 1331 ASSERT(!needsLayout()); |
| 1336 | 1332 |
| 1337 // If we didn't need paint invalidation then our children don't need as well
. | 1333 // If we didn't need paint invalidation then our children don't need as well
. |
| 1338 // Skip walking down the tree as everything should be fine below us. | 1334 // Skip walking down the tree as everything should be fine below us. |
| 1339 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) | 1335 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) |
| 1340 return; | 1336 return; |
| 1341 | 1337 |
| 1342 PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationSt
ate, paintInvalidationState.paintInvalidationContainer()); | 1338 PaintInvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationSt
ate, paintInvalidationState.paintInvalidationContainer()); |
| 1343 clearPaintInvalidationState(paintInvalidationState); | 1339 clearPaintInvalidationState(paintInvalidationState); |
| 1344 | 1340 |
| 1345 if (reason == PaintInvalidationDelayedFull) | 1341 if (reason == PaintInvalidationDelayedFull) |
| 1346 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); | 1342 paintInvalidationState.pushDelayedPaintInvalidationTarget(*this); |
| 1347 | 1343 |
| 1348 invalidatePaintOfSubtreesIfNeeded(paintInvalidationState); | 1344 invalidatePaintOfSubtreesIfNeeded(paintInvalidationState); |
| 1349 } | 1345 } |
| 1350 | 1346 |
| 1351 void LayoutObject::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& chi
ldPaintInvalidationState) | 1347 void LayoutObject::invalidatePaintOfSubtreesIfNeeded(PaintInvalidationState& chi
ldPaintInvalidationState) |
| 1352 { | 1348 { |
| 1349 ASSERT(!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()); |
| 1350 |
| 1353 for (LayoutObject* child = slowFirstChild(); child; child = child->nextSibli
ng()) { | 1351 for (LayoutObject* child = slowFirstChild(); child; child = child->nextSibli
ng()) { |
| 1354 if (!child->isOutOfFlowPositioned()) | 1352 if (!child->isOutOfFlowPositioned()) |
| 1355 child->invalidateTreeIfNeeded(childPaintInvalidationState); | 1353 child->invalidateTreeIfNeeded(childPaintInvalidationState); |
| 1356 } | 1354 } |
| 1357 } | 1355 } |
| 1358 | 1356 |
| 1359 static PassOwnPtr<TracedValue> jsonObjectForOldAndNewRects(const LayoutRect& old
Rect, const LayoutPoint& oldLocation, const LayoutRect& newRect, const LayoutPoi
nt& newLocation) | 1357 static PassOwnPtr<TracedValue> jsonObjectForOldAndNewRects(const LayoutRect& old
Rect, const LayoutPoint& oldLocation, const LayoutRect& newRect, const LayoutPoi
nt& newLocation) |
| 1360 { | 1358 { |
| 1361 OwnPtr<TracedValue> value = TracedValue::create(); | 1359 OwnPtr<TracedValue> value = TracedValue::create(); |
| 1362 addJsonObjectForRect(value.get(), "oldRect", oldRect); | 1360 addJsonObjectForRect(value.get(), "oldRect", oldRect); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1386 return; | 1384 return; |
| 1387 selectionPaintInvalidationMap = new SelectionPaintInvalidationMap(); | 1385 selectionPaintInvalidationMap = new SelectionPaintInvalidationMap(); |
| 1388 } | 1386 } |
| 1389 | 1387 |
| 1390 if (selectionRect.isEmpty()) | 1388 if (selectionRect.isEmpty()) |
| 1391 selectionPaintInvalidationMap->remove(this); | 1389 selectionPaintInvalidationMap->remove(this); |
| 1392 else | 1390 else |
| 1393 selectionPaintInvalidationMap->set(this, selectionRect); | 1391 selectionPaintInvalidationMap->set(this, selectionRect); |
| 1394 } | 1392 } |
| 1395 | 1393 |
| 1396 // TODO(wangxianzhu): Remove this for slimming paint v2 because we won't care ab
out paint invalidation rects. | |
| 1397 inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject
& paintInvalidationContainer, const PaintInvalidationState& paintInvalidationSta
te, PaintInvalidationReason invalidationReason) | 1394 inline void LayoutObject::invalidateSelectionIfNeeded(const LayoutBoxModelObject
& paintInvalidationContainer, const PaintInvalidationState& paintInvalidationSta
te, PaintInvalidationReason invalidationReason) |
| 1398 { | 1395 { |
| 1399 // Update selection rect when we are doing full invalidation (in case that t
he object is moved, composite status changed, etc.) | 1396 // Update selection rect when we are doing full invalidation (in case that t
he object is moved, composite status changed, etc.) |
| 1400 // or shouldInvalidationSelection is set (in case that the selection itself
changed). | 1397 // or shouldInvalidationSelection is set (in case that the selection itself
changed). |
| 1401 bool fullInvalidation = view()->doingFullPaintInvalidation() || isFullPaintI
nvalidationReason(invalidationReason); | 1398 bool fullInvalidation = view()->doingFullPaintInvalidation() || isFullPaintI
nvalidationReason(invalidationReason); |
| 1402 if (!fullInvalidation && !shouldInvalidateSelection()) | 1399 if (!fullInvalidation && !shouldInvalidateSelection()) |
| 1403 return; | 1400 return; |
| 1404 | 1401 |
| 1405 LayoutRect oldSelectionRect = previousSelectionRectForPaintInvalidation(); | 1402 LayoutRect oldSelectionRect = previousSelectionRectForPaintInvalidation(); |
| 1406 LayoutRect newSelectionRect = selectionRectForPaintInvalidation(&paintInvali
dationContainer); | 1403 LayoutRect newSelectionRect = selectionRectForPaintInvalidation(&paintInvali
dationContainer); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1429 PaintLayer& layer = paintInvalidationState.enclosingSelfPaintingLayer(*t
his); | 1426 PaintLayer& layer = paintInvalidationState.enclosingSelfPaintingLayer(*t
his); |
| 1430 if (layer.layoutObject() != this) | 1427 if (layer.layoutObject() != this) |
| 1431 layer.setNeedsPaintPhaseDescendantOutlines(); | 1428 layer.setNeedsPaintPhaseDescendantOutlines(); |
| 1432 } | 1429 } |
| 1433 | 1430 |
| 1434 LayoutView* v = view(); | 1431 LayoutView* v = view(); |
| 1435 if (v->document().printing()) | 1432 if (v->document().printing()) |
| 1436 return PaintInvalidationNone; // Don't invalidate paints if we're printi
ng. | 1433 return PaintInvalidationNone; // Don't invalidate paints if we're printi
ng. |
| 1437 | 1434 |
| 1438 const LayoutRect oldBounds = previousPaintInvalidationRect(); | 1435 const LayoutRect oldBounds = previousPaintInvalidationRect(); |
| 1439 const LayoutPoint oldLocation = RuntimeEnabledFeatures::slimmingPaintInvalid
ationEnabled() ? LayoutPoint() : previousPositionFromPaintInvalidationBacking(); | 1436 const LayoutPoint oldLocation = previousPositionFromPaintInvalidationBacking
(); |
| 1440 LayoutRect newBounds = boundsRectForPaintInvalidation(paintInvalidationConta
iner, &paintInvalidationState); | 1437 LayoutRect newBounds = boundsRectForPaintInvalidation(paintInvalidationConta
iner, &paintInvalidationState); |
| 1441 LayoutPoint newLocation = RuntimeEnabledFeatures::slimmingPaintInvalidationE
nabled() ? LayoutPoint() : PaintLayer::positionFromPaintInvalidationBacking(this
, &paintInvalidationContainer, &paintInvalidationState); | 1438 LayoutPoint newLocation = PaintLayer::positionFromPaintInvalidationBacking(t
his, &paintInvalidationContainer, &paintInvalidationState); |
| 1442 | 1439 |
| 1443 // Composited scrolling should not be included in the bounds and position tr
acking, because the graphics layer backing the scroller | 1440 // Composited scrolling should not be included in the bounds and position tr
acking, because the graphics layer backing the scroller |
| 1444 // does not move on scroll. | 1441 // does not move on scroll. |
| 1445 if (paintInvalidationContainer.usesCompositedScrolling() && &paintInvalidati
onContainer != this) { | 1442 if (paintInvalidationContainer.usesCompositedScrolling() && &paintInvalidati
onContainer != this) { |
| 1446 LayoutSize inverseOffset(toLayoutBox(&paintInvalidationContainer)->scrol
ledContentOffset()); | 1443 LayoutSize inverseOffset(toLayoutBox(&paintInvalidationContainer)->scrol
ledContentOffset()); |
| 1447 newLocation.move(inverseOffset); | 1444 newLocation.move(inverseOffset); |
| 1448 newBounds.move(inverseOffset); | 1445 newBounds.move(inverseOffset); |
| 1449 } | 1446 } |
| 1450 | 1447 |
| 1451 setPreviousPaintInvalidationRect(newBounds); | 1448 setPreviousPaintInvalidationRect(newBounds); |
| 1452 if (!RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) | 1449 setPreviousPositionFromPaintInvalidationBacking(newLocation); |
| 1453 setPreviousPositionFromPaintInvalidationBacking(newLocation); | |
| 1454 | 1450 |
| 1455 if (!shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() &&
!paintInvalidationState.forcedSubtreeInvalidationWithinContainer()) { | 1451 if (!shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState() &&
!paintInvalidationState.forcedSubtreeInvalidationWithinContainer()) { |
| 1456 ASSERT(paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinC
ontainer()); | 1452 ASSERT(paintInvalidationState.forcedSubtreeInvalidationRectUpdateWithinC
ontainer()); |
| 1457 return PaintInvalidationNone; | 1453 return PaintInvalidationNone; |
| 1458 } | 1454 } |
| 1459 | 1455 |
| 1460 PaintInvalidationReason invalidationReason = getPaintInvalidationReason(pain
tInvalidationContainer, oldBounds, oldLocation, newBounds, newLocation); | 1456 PaintInvalidationReason invalidationReason = getPaintInvalidationReason(pain
tInvalidationContainer, oldBounds, oldLocation, newBounds, newLocation); |
| 1461 | 1457 |
| 1462 // We need to invalidate the selection before checking for whether we are do
ing a full invalidation. | 1458 // We need to invalidate the selection before checking for whether we are do
ing a full invalidation. |
| 1463 // This is because we need to update the old rect regardless. | 1459 // This is because we need to update the old rect regardless. |
| (...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2623 } | 2619 } |
| 2624 | 2620 |
| 2625 return o; | 2621 return o; |
| 2626 } | 2622 } |
| 2627 | 2623 |
| 2628 LayoutObject* LayoutObject::containerCrossingFrameBoundaries() const | 2624 LayoutObject* LayoutObject::containerCrossingFrameBoundaries() const |
| 2629 { | 2625 { |
| 2630 return isLayoutView() ? frame()->ownerLayoutObject() : container(); | 2626 return isLayoutView() ? frame()->ownerLayoutObject() : container(); |
| 2631 } | 2627 } |
| 2632 | 2628 |
| 2629 LayoutObject* LayoutObject::parentCrossingFrameBoundaries() const |
| 2630 { |
| 2631 return isLayoutView() ? frame()->ownerLayoutObject() : parent(); |
| 2632 } |
| 2633 |
| 2633 bool LayoutObject::isSelectionBorder() const | 2634 bool LayoutObject::isSelectionBorder() const |
| 2634 { | 2635 { |
| 2635 SelectionState st = getSelectionState(); | 2636 SelectionState st = getSelectionState(); |
| 2636 return st == SelectionStart || st == SelectionEnd || st == SelectionBoth; | 2637 return st == SelectionStart || st == SelectionEnd || st == SelectionBoth; |
| 2637 } | 2638 } |
| 2638 | 2639 |
| 2639 inline void LayoutObject::clearLayoutRootIfNeeded() const | 2640 inline void LayoutObject::clearLayoutRootIfNeeded() const |
| 2640 { | 2641 { |
| 2641 if (FrameView* view = frameView()) { | 2642 if (FrameView* view = frameView()) { |
| 2642 if (!documentBeingDestroyed()) | 2643 if (!documentBeingDestroyed()) |
| (...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3438 return PaintInvalidationForcedByLayout; | 3439 return PaintInvalidationForcedByLayout; |
| 3439 case DocumentLifecycle::InCompositingUpdate: | 3440 case DocumentLifecycle::InCompositingUpdate: |
| 3440 return PaintInvalidationCompositingUpdate; | 3441 return PaintInvalidationCompositingUpdate; |
| 3441 default: | 3442 default: |
| 3442 return PaintInvalidationFull; | 3443 return PaintInvalidationFull; |
| 3443 } | 3444 } |
| 3444 } | 3445 } |
| 3445 | 3446 |
| 3446 inline void LayoutObject::markContainerChainForPaintInvalidation() | 3447 inline void LayoutObject::markContainerChainForPaintInvalidation() |
| 3447 { | 3448 { |
| 3449 if (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()) { |
| 3450 // We use PaintPropertyTreeBuilder, which walks layout tree in DOM order
, for paint invalidation, |
| 3451 // so we need to mark paint invalidation flags also in DOM order (instea
d of containing block order). |
| 3452 for (LayoutObject* ancestor = this->parentCrossingFrameBoundaries(); anc
estor && !ancestor->shouldCheckForPaintInvalidationRegardlessOfPaintInvalidation
State(); ancestor = ancestor->parentCrossingFrameBoundaries()) |
| 3453 ancestor->m_bitfields.setChildShouldCheckForPaintInvalidation(true); |
| 3454 return; |
| 3455 } |
| 3456 |
| 3448 for (LayoutObject* container = this->containerCrossingFrameBoundaries(); con
tainer && !container->shouldCheckForPaintInvalidationRegardlessOfPaintInvalidati
onState(); container = container->containerCrossingFrameBoundaries()) | 3457 for (LayoutObject* container = this->containerCrossingFrameBoundaries(); con
tainer && !container->shouldCheckForPaintInvalidationRegardlessOfPaintInvalidati
onState(); container = container->containerCrossingFrameBoundaries()) |
| 3449 container->m_bitfields.setChildShouldCheckForPaintInvalidation(true); | 3458 container->m_bitfields.setChildShouldCheckForPaintInvalidation(true); |
| 3450 } | 3459 } |
| 3451 | 3460 |
| 3452 void LayoutObject::setShouldInvalidateSelection() | 3461 void LayoutObject::setShouldInvalidateSelection() |
| 3453 { | 3462 { |
| 3454 if (!canUpdateSelectionOnRootLineBoxes()) | 3463 if (!canUpdateSelectionOnRootLineBoxes()) |
| 3455 return; | 3464 return; |
| 3456 m_bitfields.setShouldInvalidateSelection(true); | 3465 m_bitfields.setShouldInvalidateSelection(true); |
| 3457 markContainerChainForPaintInvalidation(); | 3466 markContainerChainForPaintInvalidation(); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3728 const blink::LayoutObject* root = object1; | 3737 const blink::LayoutObject* root = object1; |
| 3729 while (root->parent()) | 3738 while (root->parent()) |
| 3730 root = root->parent(); | 3739 root = root->parent(); |
| 3731 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0); | 3740 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0); |
| 3732 } else { | 3741 } else { |
| 3733 fprintf(stderr, "Cannot showLayoutTree. Root is (nil)\n"); | 3742 fprintf(stderr, "Cannot showLayoutTree. Root is (nil)\n"); |
| 3734 } | 3743 } |
| 3735 } | 3744 } |
| 3736 | 3745 |
| 3737 #endif | 3746 #endif |
| OLD | NEW |