OLD | NEW |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/trees/layer_tree_host_common.h" | 5 #include "cc/trees/layer_tree_host_common.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "cc/base/math_util.h" | 10 #include "cc/base/math_util.h" |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 bool atLeastTwoLayersInSubtreeDrawContent = numDescendantsThatDrawContent >
0 && (layer->DrawsContent() || numDescendantsThatDrawContent > 1); | 309 bool atLeastTwoLayersInSubtreeDrawContent = numDescendantsThatDrawContent >
0 && (layer->DrawsContent() || numDescendantsThatDrawContent > 1); |
310 | 310 |
311 if (layer->opacity() != 1.f && !layer->preserves_3d() && atLeastTwoLayersInS
ubtreeDrawContent) { | 311 if (layer->opacity() != 1.f && !layer->preserves_3d() && atLeastTwoLayersInS
ubtreeDrawContent) { |
312 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostCommon::requireSurface opacity"
); | 312 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostCommon::requireSurface opacity"
); |
313 return true; | 313 return true; |
314 } | 314 } |
315 | 315 |
316 return false; | 316 return false; |
317 } | 317 } |
318 | 318 |
| 319 static LayerImpl* nextTargetSurface(LayerImpl* layer) |
| 320 { |
| 321 return layer->parent() ? layer->parent()->render_target() : 0; |
| 322 } |
| 323 |
| 324 void applyPositionAdjustment(Layer*, Layer*, const gfx::Transform&, gfx::Transfo
rm*) { } |
| 325 void applyPositionAdjustment(LayerImpl* layer, LayerImpl* container, const gfx::
Transform& scrollCompensation, gfx::Transform* combinedTransform) |
| 326 { |
| 327 if (layer->position_constraint().is_fixed_position()) { |
| 328 // Special case: this layer is a composited fixed-position layer; we nee
d to |
| 329 // explicitly compensate for all ancestors' nonzero scrollDeltas to keep
this layer |
| 330 // fixed correctly. |
| 331 // Note carefully: this is Concat, not Preconcat (currentScrollCompensat
ion * combinedTransform). |
| 332 combinedTransform->ConcatTransform(scrollCompensation); |
| 333 |
| 334 // For right-edge or bottom-edge anchored fixed position layers, |
| 335 // the layer should relocate itself if the container changes its size. |
| 336 bool fixedToRightEdge = layer->position_constraint().is_fixed_to_right_e
dge(); |
| 337 bool fixedToBottomEdge = layer->position_constraint().is_fixed_to_bottom
_edge(); |
| 338 gfx::Vector2dF positionOffset = container ? container->fixed_container_s
ize_delta() : gfx::Vector2dF(); |
| 339 positionOffset.set_x(fixedToRightEdge ? positionOffset.x() : 0); |
| 340 positionOffset.set_y(fixedToBottomEdge ? positionOffset.y() : 0); |
| 341 if (positionOffset.IsZero()) |
| 342 return; |
| 343 |
| 344 // To apply bottom-right anchor compensation in the container's layer sp
ace, |
| 345 // the following steps need to be done: |
| 346 // Step 1a. transform from target surface space to the container's t
arget surface space |
| 347 // Step 1b. transform from container's target surface space to the c
ontainer's layer space |
| 348 // Step 2. apply the compensation |
| 349 // Step 3. transform back to target surface space |
| 350 |
| 351 gfx::Transform targetSurfaceSpaceToContainerLayerSpace; |
| 352 |
| 353 // Step 1a |
| 354 LayerImpl* containerTargetSurface = container ? container->render_target
() : 0; |
| 355 for (LayerImpl* currentTargetSurface = nextTargetSurface(layer); |
| 356 currentTargetSurface && currentTargetSurface != containerTargetSurf
ace; |
| 357 currentTargetSurface = nextTargetSurface(currentTargetSurface)) { |
| 358 targetSurfaceSpaceToContainerLayerSpace.ConcatTransform(currentTarge
tSurface->render_surface()->draw_transform()); |
| 359 } |
| 360 |
| 361 // Step 1b |
| 362 gfx::Transform containerTargetSurfaceSpaceToContainerLayerSpace; |
| 363 if (container && container->draw_transform().GetInverse(&containerTarget
SurfaceSpaceToContainerLayerSpace)) |
| 364 targetSurfaceSpaceToContainerLayerSpace.ConcatTransform(containerTar
getSurfaceSpaceToContainerLayerSpace); |
| 365 |
| 366 combinedTransform->ConcatTransform(targetSurfaceSpaceToContainerLayerSpa
ce); |
| 367 |
| 368 // Step 2 |
| 369 combinedTransform->Translate(positionOffset.x(), positionOffset.y()); |
| 370 |
| 371 // Step 3 |
| 372 gfx::Transform containerLayerSpaceTotargetSurfaceSpace; |
| 373 if (targetSurfaceSpaceToContainerLayerSpace.GetInverse(&containerLayerSp
aceTotargetSurfaceSpace)) |
| 374 combinedTransform->ConcatTransform(containerLayerSpaceTotargetSurfac
eSpace); |
| 375 } |
| 376 } |
| 377 |
319 gfx::Transform computeScrollCompensationForThisLayer(LayerImpl* scrollingLayer,
const gfx::Transform& parentMatrix) | 378 gfx::Transform computeScrollCompensationForThisLayer(LayerImpl* scrollingLayer,
const gfx::Transform& parentMatrix) |
320 { | 379 { |
321 // For every layer that has non-zero scrollDelta, we have to compute a trans
form that can undo the | 380 // For every layer that has non-zero scrollDelta, we have to compute a trans
form that can undo the |
322 // scrollDelta translation. In particular, we want this matrix to premultipl
y a fixed-position layer's | 381 // scrollDelta translation. In particular, we want this matrix to premultipl
y a fixed-position layer's |
323 // parentMatrix, so we design this transform in three steps as follows. The
steps described here apply | 382 // parentMatrix, so we design this transform in three steps as follows. The
steps described here apply |
324 // from right-to-left, so Step 1 would be the right-most matrix: | 383 // from right-to-left, so Step 1 would be the right-most matrix: |
325 // | 384 // |
326 // Step 1. transform from target surface space to the exact space where
scrollDelta is actually applied. | 385 // Step 1. transform from target surface space to the exact space where
scrollDelta is actually applied. |
327 // -- this is inverse of the matrix in step 3 | 386 // -- this is inverse of the matrix in step 3 |
328 // Step 2. undo the scrollDelta | 387 // Step 2. undo the scrollDelta |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 static void roundTranslationComponents(gfx::Transform* transform) | 605 static void roundTranslationComponents(gfx::Transform* transform) |
547 { | 606 { |
548 transform->matrix().setDouble(0, 3, MathUtil::Round(transform->matrix().getD
ouble(0, 3))); | 607 transform->matrix().setDouble(0, 3, MathUtil::Round(transform->matrix().getD
ouble(0, 3))); |
549 transform->matrix().setDouble(1, 3, MathUtil::Round(transform->matrix().getD
ouble(1, 3))); | 608 transform->matrix().setDouble(1, 3, MathUtil::Round(transform->matrix().getD
ouble(1, 3))); |
550 } | 609 } |
551 | 610 |
552 // Recursively walks the layer tree starting at the given node and computes all
the | 611 // Recursively walks the layer tree starting at the given node and computes all
the |
553 // necessary transformations, clipRects, render surfaces, etc. | 612 // necessary transformations, clipRects, render surfaces, etc. |
554 template<typename LayerType, typename LayerList, typename RenderSurfaceType> | 613 template<typename LayerType, typename LayerList, typename RenderSurfaceType> |
555 static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo
rm& parentMatrix, | 614 static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo
rm& parentMatrix, |
556 const gfx::Transform& fullHierarchyMatrix, const gfx::Transform& currentScro
llCompensationMatrix, | 615 const gfx::Transform& fullHierarchyMatrix, const gfx::Transform& currentScro
llCompensationMatrix, LayerType* currentFixedContainer, |
557 const gfx::Rect& clipRectFromAncestor, const gfx::Rect& clipRectFromAncestor
InDescendantSpace, bool ancestorClipsSubtree, | 616 const gfx::Rect& clipRectFromAncestor, const gfx::Rect& clipRectFromAncestor
InDescendantSpace, bool ancestorClipsSubtree, |
558 RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceL
ayerList, LayerList& layerList, | 617 RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceL
ayerList, LayerList& layerList, |
559 LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, float
pageScaleFactor, bool subtreeCanUseLCDText, | 618 LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, float
pageScaleFactor, bool subtreeCanUseLCDText, |
560 gfx::Rect& drawableContentRectOfSubtree, bool updateTilePriorities) | 619 gfx::Rect& drawableContentRectOfSubtree, bool updateTilePriorities) |
561 { | 620 { |
562 // This function computes the new matrix transformations recursively for thi
s | 621 // This function computes the new matrix transformations recursively for thi
s |
563 // layer and all its descendants. It also computes the appropriate render su
rfaces. | 622 // layer and all its descendants. It also computes the appropriate render su
rfaces. |
564 // Some important points to remember: | 623 // Some important points to remember: |
565 // | 624 // |
566 // 0. Here, transforms are notated in Matrix x Vector order, and in words we
describe what | 625 // 0. Here, transforms are notated in Matrix x Vector order, and in words we
describe what |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 // computation of contentsScale above. | 761 // computation of contentsScale above. |
703 // Note carefully: this is Concat, not Preconcat (implTransform * combinedTr
ansform). | 762 // Note carefully: this is Concat, not Preconcat (implTransform * combinedTr
ansform). |
704 combinedTransform.ConcatTransform(layer->impl_transform()); | 763 combinedTransform.ConcatTransform(layer->impl_transform()); |
705 | 764 |
706 if (!animatingTransformToTarget && layer->scrollable() && combinedTransform.
IsScaleOrTranslation()) { | 765 if (!animatingTransformToTarget && layer->scrollable() && combinedTransform.
IsScaleOrTranslation()) { |
707 // Align the scrollable layer's position to screen space pixels to avoid
blurriness. | 766 // Align the scrollable layer's position to screen space pixels to avoid
blurriness. |
708 // To avoid side-effects, do this only if the transform is simple. | 767 // To avoid side-effects, do this only if the transform is simple. |
709 roundTranslationComponents(&combinedTransform); | 768 roundTranslationComponents(&combinedTransform); |
710 } | 769 } |
711 | 770 |
712 if (layer->fixed_to_container_layer()) { | 771 // Apply adjustment from position constraints. |
713 // Special case: this layer is a composited fixed-position layer; we nee
d to | 772 applyPositionAdjustment(layer, currentFixedContainer, currentScrollCompensat
ionMatrix, &combinedTransform); |
714 // explicitly compensate for all ancestors' nonzero scrollDeltas to keep
this layer | |
715 // fixed correctly. | |
716 // Note carefully: this is Concat, not Preconcat (currentScrollCompensat
ion * combinedTransform). | |
717 combinedTransform.ConcatTransform(currentScrollCompensationMatrix); | |
718 } | |
719 | 773 |
720 // The drawTransform that gets computed below is effectively the layer's dra
wTransform, unless | 774 // The drawTransform that gets computed below is effectively the layer's dra
wTransform, unless |
721 // the layer itself creates a renderSurface. In that case, the renderSurface
re-parents the transforms. | 775 // the layer itself creates a renderSurface. In that case, the renderSurface
re-parents the transforms. |
722 layerDrawProperties.target_space_transform = combinedTransform; | 776 layerDrawProperties.target_space_transform = combinedTransform; |
723 // M[draw] = M[parent] * LT * S[layer2content] | 777 // M[draw] = M[parent] * LT * S[layer2content] |
724 layerDrawProperties.target_space_transform.Scale(1.0 / layer->contents_scale
_x(), 1.0 / layer->contents_scale_y()); | 778 layerDrawProperties.target_space_transform.Scale(1.0 / layer->contents_scale
_x(), 1.0 / layer->contents_scale_y()); |
725 | 779 |
726 // layerScreenSpaceTransform represents the transform between root layer's "
screen space" and local content space. | 780 // layerScreenSpaceTransform represents the transform between root layer's "
screen space" and local content space. |
727 layerDrawProperties.screen_space_transform = fullHierarchyMatrix; | 781 layerDrawProperties.screen_space_transform = fullHierarchyMatrix; |
728 if (!layer->preserves_3d()) | 782 if (!layer->preserves_3d()) |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 | 945 |
892 LayerList& descendants = (layer->render_surface() ? layer->render_surface()-
>layer_list() : layerList); | 946 LayerList& descendants = (layer->render_surface() ? layer->render_surface()-
>layer_list() : layerList); |
893 | 947 |
894 // Any layers that are appended after this point are in the layer's subtree
and should be included in the sorting process. | 948 // Any layers that are appended after this point are in the layer's subtree
and should be included in the sorting process. |
895 unsigned sortingStartIndex = descendants.size(); | 949 unsigned sortingStartIndex = descendants.size(); |
896 | 950 |
897 if (!layerShouldBeSkipped(layer)) | 951 if (!layerShouldBeSkipped(layer)) |
898 descendants.push_back(layer); | 952 descendants.push_back(layer); |
899 | 953 |
900 gfx::Transform nextScrollCompensationMatrix = computeScrollCompensationMatri
xForChildren(layer, parentMatrix, currentScrollCompensationMatrix);; | 954 gfx::Transform nextScrollCompensationMatrix = computeScrollCompensationMatri
xForChildren(layer, parentMatrix, currentScrollCompensationMatrix);; |
| 955 LayerType* nextFixedContainer = layer->is_container_for_fixed_position_layer
s() ? layer : currentFixedContainer; |
901 | 956 |
902 gfx::Rect accumulatedDrawableContentRectOfChildren; | 957 gfx::Rect accumulatedDrawableContentRectOfChildren; |
903 for (size_t i = 0; i < layer->children().size(); ++i) { | 958 for (size_t i = 0; i < layer->children().size(); ++i) { |
904 LayerType* child = LayerTreeHostCommon::getChildAsRawPtr(layer->children
(), i); | 959 LayerType* child = LayerTreeHostCommon::getChildAsRawPtr(layer->children
(), i); |
905 gfx::Rect drawableContentRectOfChildSubtree; | 960 gfx::Rect drawableContentRectOfChildSubtree; |
906 calculateDrawPropertiesInternal<LayerType, LayerList, RenderSurfaceType>
(child, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, | 961 calculateDrawPropertiesInternal<LayerType, LayerList, RenderSurfaceType>
(child, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, nextF
ixedContainer, |
907
clipRectForSubtree, clipRectForSubtreeInDescendantSpace, subtreeShouldBeClipped
, nearestAncestorThatMovesPixels, | 962
clipRectForSubtree, clipRectForSubtreeInDescendantSpace, subtreeShouldBeClipped
, nearestAncestorThatMovesPixels, |
908
renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFa
ctor, pageScaleFactor, | 963
renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFa
ctor, pageScaleFactor, |
909
subtreeCanUseLCDText, drawableContentRectOfChildSubtree, updateTilePriorities); | 964
subtreeCanUseLCDText, drawableContentRectOfChildSubtree, updateTilePriorities); |
910 if (!drawableContentRectOfChildSubtree.IsEmpty()) { | 965 if (!drawableContentRectOfChildSubtree.IsEmpty()) { |
911 accumulatedDrawableContentRectOfChildren.Union(drawableContentRectOf
ChildSubtree); | 966 accumulatedDrawableContentRectOfChildren.Union(drawableContentRectOf
ChildSubtree); |
912 if (child->render_surface()) | 967 if (child->render_surface()) |
913 descendants.push_back(child); | 968 descendants.push_back(child); |
914 } | 969 } |
915 } | 970 } |
916 | 971 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 // The root layer's renderSurface should receive the deviceViewport as the i
nitial clipRect. | 1094 // The root layer's renderSurface should receive the deviceViewport as the i
nitial clipRect. |
1040 bool subtreeShouldBeClipped = true; | 1095 bool subtreeShouldBeClipped = true; |
1041 gfx::Rect deviceViewportRect(gfx::Point(), deviceViewportSize); | 1096 gfx::Rect deviceViewportRect(gfx::Point(), deviceViewportSize); |
1042 bool updateTilePriorities = false; | 1097 bool updateTilePriorities = false; |
1043 | 1098 |
1044 // This function should have received a root layer. | 1099 // This function should have received a root layer. |
1045 DCHECK(isRootLayer(rootLayer)); | 1100 DCHECK(isRootLayer(rootLayer)); |
1046 | 1101 |
1047 preCalculateMetaInformation<Layer>(rootLayer); | 1102 preCalculateMetaInformation<Layer>(rootLayer); |
1048 calculateDrawPropertiesInternal<Layer, std::vector<scoped_refptr<Layer> >, R
enderSurface>( | 1103 calculateDrawPropertiesInternal<Layer, std::vector<scoped_refptr<Layer> >, R
enderSurface>( |
1049 rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, | 1104 rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, 0, |
1050 deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, rende
rSurfaceLayerList, | 1105 deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, rende
rSurfaceLayerList, |
1051 dummyLayerList, 0, maxTextureSize, | 1106 dummyLayerList, 0, maxTextureSize, |
1052 deviceScaleFactor, pageScaleFactor, canUseLCDText, totalDrawableContentR
ect, | 1107 deviceScaleFactor, pageScaleFactor, canUseLCDText, totalDrawableContentR
ect, |
1053 updateTilePriorities); | 1108 updateTilePriorities); |
1054 | 1109 |
1055 // The dummy layer list should not have been used. | 1110 // The dummy layer list should not have been used. |
1056 DCHECK(dummyLayerList.size() == 0); | 1111 DCHECK(dummyLayerList.size() == 0); |
1057 // A root layer renderSurface should always exist after calculateDrawPropert
ies. | 1112 // A root layer renderSurface should always exist after calculateDrawPropert
ies. |
1058 DCHECK(rootLayer->render_surface()); | 1113 DCHECK(rootLayer->render_surface()); |
1059 } | 1114 } |
1060 | 1115 |
1061 void LayerTreeHostCommon::calculateDrawProperties(LayerImpl* rootLayer, const gf
x::Size& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, int
maxTextureSize, bool canUseLCDText, std::vector<LayerImpl*>& renderSurfaceLayer
List, bool updateTilePriorities) | 1116 void LayerTreeHostCommon::calculateDrawProperties(LayerImpl* rootLayer, const gf
x::Size& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, int
maxTextureSize, bool canUseLCDText, std::vector<LayerImpl*>& renderSurfaceLayer
List, bool updateTilePriorities) |
1062 { | 1117 { |
1063 gfx::Rect totalDrawableContentRect; | 1118 gfx::Rect totalDrawableContentRect; |
1064 gfx::Transform identityMatrix; | 1119 gfx::Transform identityMatrix; |
1065 gfx::Transform deviceScaleTransform; | 1120 gfx::Transform deviceScaleTransform; |
1066 deviceScaleTransform.Scale(deviceScaleFactor, deviceScaleFactor); | 1121 deviceScaleTransform.Scale(deviceScaleFactor, deviceScaleFactor); |
1067 std::vector<LayerImpl*> dummyLayerList; | 1122 std::vector<LayerImpl*> dummyLayerList; |
1068 LayerSorter layerSorter; | 1123 LayerSorter layerSorter; |
1069 | 1124 |
1070 // The root layer's renderSurface should receive the deviceViewport as the i
nitial clipRect. | 1125 // The root layer's renderSurface should receive the deviceViewport as the i
nitial clipRect. |
1071 bool subtreeShouldBeClipped = true; | 1126 bool subtreeShouldBeClipped = true; |
1072 gfx::Rect deviceViewportRect(gfx::Point(), deviceViewportSize); | 1127 gfx::Rect deviceViewportRect(gfx::Point(), deviceViewportSize); |
1073 | 1128 |
1074 // This function should have received a root layer. | 1129 // This function should have received a root layer. |
1075 DCHECK(isRootLayer(rootLayer)); | 1130 DCHECK(isRootLayer(rootLayer)); |
1076 | 1131 |
1077 preCalculateMetaInformation<LayerImpl>(rootLayer); | 1132 preCalculateMetaInformation<LayerImpl>(rootLayer); |
1078 calculateDrawPropertiesInternal<LayerImpl, std::vector<LayerImpl*>, RenderSu
rfaceImpl>( | 1133 calculateDrawPropertiesInternal<LayerImpl, std::vector<LayerImpl*>, RenderSu
rfaceImpl>( |
1079 rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, | 1134 rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, 0, |
1080 deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, rende
rSurfaceLayerList, | 1135 deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, rende
rSurfaceLayerList, |
1081 dummyLayerList, &layerSorter, maxTextureSize, | 1136 dummyLayerList, &layerSorter, maxTextureSize, |
1082 deviceScaleFactor, pageScaleFactor, canUseLCDText, totalDrawableContentR
ect, | 1137 deviceScaleFactor, pageScaleFactor, canUseLCDText, totalDrawableContentR
ect, |
1083 updateTilePriorities); | 1138 updateTilePriorities); |
1084 | 1139 |
1085 // The dummy layer list should not have been used. | 1140 // The dummy layer list should not have been used. |
1086 DCHECK(dummyLayerList.size() == 0); | 1141 DCHECK(dummyLayerList.size() == 0); |
1087 // A root layer renderSurface should always exist after calculateDrawPropert
ies. | 1142 // A root layer renderSurface should always exist after calculateDrawPropert
ies. |
1088 DCHECK(rootLayer->render_surface()); | 1143 DCHECK(rootLayer->render_surface()); |
1089 } | 1144 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 | 1272 |
1218 // At this point, we think the point does hit the touch event handler region o
n the layer, but we need to walk up | 1273 // At this point, we think the point does hit the touch event handler region o
n the layer, but we need to walk up |
1219 // the parents to ensure that the layer was not clipped in such a way that the | 1274 // the parents to ensure that the layer was not clipped in such a way that the |
1220 // hit point actually should not hit the layer. | 1275 // hit point actually should not hit the layer. |
1221 if (pointIsClippedBySurfaceOrClipRect(screenSpacePoint, layerImpl)) | 1276 if (pointIsClippedBySurfaceOrClipRect(screenSpacePoint, layerImpl)) |
1222 return false; | 1277 return false; |
1223 | 1278 |
1224 return true; | 1279 return true; |
1225 } | 1280 } |
1226 } // namespace cc | 1281 } // namespace cc |
OLD | NEW |