OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. | 5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. |
6 | 6 |
7 #include "ui/views/view.h" | 7 #include "ui/views/view.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
768 return; | 768 return; |
769 // The cull_set may allow us to skip painting without canvas construction or | 769 // The cull_set may allow us to skip painting without canvas construction or |
770 // even canvas rect intersection. | 770 // even canvas rect intersection. |
771 if (!cull_set.ShouldPaint(this)) | 771 if (!cull_set.ShouldPaint(this)) |
772 return; | 772 return; |
773 | 773 |
774 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); | 774 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); |
775 | 775 |
776 gfx::ScopedCanvas scoped_canvas(canvas); | 776 gfx::ScopedCanvas scoped_canvas(canvas); |
777 | 777 |
778 // Paint this View and its children, setting the clip rect to the bounds | 778 // If the view is backed by a layer, it should paint with itself as the origin |
779 // of this View and translating the origin to the local bounds' top left | 779 // rather than relative to its parent. |
780 // point. | 780 if (!layer()) { |
781 // | 781 // Set the clip rect to the bounds of this View and translating the origin |
782 // Note that the X (or left) position we pass to ClipRectInt takes into | 782 // to the local bounds' top left point. |
783 // consideration whether or not the view uses a right-to-left layout so that | 783 // |
784 // we paint our view in its mirrored position if need be. | 784 // Note that the X (or left) position we pass to ClipRectInt takes into |
785 gfx::Rect clip_rect = bounds(); | 785 // consideration whether or not the view uses a right-to-left layout so that |
786 clip_rect.Inset(clip_insets_); | 786 // we paint our view in its mirrored position if need be. |
787 if (parent_) | 787 gfx::Rect clip_rect = bounds(); |
788 clip_rect.set_x(parent_->GetMirroredXForRect(clip_rect)); | 788 clip_rect.Inset(clip_insets_); |
789 canvas->ClipRect(clip_rect); | 789 if (parent_) |
790 if (canvas->IsClipEmpty()) | 790 clip_rect.set_x(parent_->GetMirroredXForRect(clip_rect)); |
791 return; | 791 canvas->ClipRect(clip_rect); |
792 if (canvas->IsClipEmpty()) | |
793 return; | |
792 | 794 |
793 // Non-empty clip, translate the graphics such that 0,0 corresponds to where | 795 // Non-empty clip, translate the graphics such that 0,0 corresponds to where |
794 // this view is located (related to its parent). | 796 // this view is located (related to its parent). |
795 canvas->Translate(GetMirroredPosition().OffsetFromOrigin()); | 797 canvas->Translate(GetMirroredPosition().OffsetFromOrigin()); |
796 canvas->Transform(GetTransform()); | 798 canvas->Transform(GetTransform()); |
799 } | |
797 | 800 |
798 // If we are a paint root, we need to construct our own CullSet object for | 801 { |
799 // propagation to our children. | 802 // If the View we are about to paint requested the canvas to be flipped, we |
800 if (IsPaintRoot()) { | 803 // should change the transform appropriately. |
801 if (!bounds_tree_) | 804 // The canvas mirroring is undone once the View is done painting so that we |
802 bounds_tree_.reset(new BoundsTree(2, 5)); | 805 // don't pass the canvas with the mirrored transform to Views that didn't |
803 | 806 // request the canvas to be flipped. |
804 // Recompute our bounds tree as needed. | 807 gfx::ScopedCanvas scoped(canvas); |
805 UpdateRootBounds(bounds_tree_.get(), gfx::Vector2d()); | 808 if (FlipCanvasOnPaintForRTLUI()) { |
806 | 809 canvas->Translate(gfx::Vector2d(width(), 0)); |
807 // Grab the clip rect from the supplied canvas to use as the query rect. | 810 canvas->Scale(-1, 1); |
808 gfx::Rect canvas_bounds; | |
809 if (!canvas->GetClipBounds(&canvas_bounds)) { | |
810 NOTREACHED() << "Failed to get clip bounds from the canvas!"; | |
811 return; | |
812 } | 811 } |
813 | 812 |
814 // Now query our bounds_tree_ for a set of damaged views that intersect | 813 // Delegate painting the contents of the View to the virtual OnPaint method. |
815 // our canvas bounds. | 814 OnPaint(canvas); |
816 scoped_ptr<base::hash_set<intptr_t>> damaged_views( | |
817 new base::hash_set<intptr_t>()); | |
818 bounds_tree_->AppendIntersectingRecords(canvas_bounds, damaged_views.get()); | |
819 // Construct a CullSet to wrap the damaged views set, it will delete it | |
820 // for us on scope exit. | |
821 CullSet paint_root_cull_set(damaged_views.Pass()); | |
822 // Paint all descendents using our new cull set. | |
823 PaintCommon(canvas, paint_root_cull_set); | |
824 } else { | |
825 // Not a paint root, so we can proceed as normal. | |
826 PaintCommon(canvas, cull_set); | |
827 } | 815 } |
816 | |
817 // If the view is not a paint root, it should come with a CullSet already | |
818 // constructed for use. | |
819 // TODO(danakj): However, if it is a paint root but is also backed by a | |
820 // layer(), we are unable to construct a CullSet because the bounds() do not | |
821 // match the position we will be painting at and UpdateRootBounds() does the | |
sky
2015/03/25 22:55:05
I don't understand, bounds in the cullset are rela
danakj
2015/03/25 22:57:11
I didn't dig too deep, but when I remove the ||lay
| |
822 // wrong thing. | |
823 if (!IsPaintRoot() || layer()) { | |
824 PaintChildren(canvas, cull_set); | |
825 return; | |
826 } | |
827 | |
828 // We are a paint root, so we construct our own CullSet object for propagation | |
829 // to our children. | |
830 if (!bounds_tree_) | |
831 bounds_tree_.reset(new BoundsTree(2, 5)); | |
832 | |
833 // Recompute our bounds tree as needed. | |
834 UpdateRootBounds(bounds_tree_.get(), gfx::Vector2d()); | |
835 | |
836 // Grab the clip rect from the supplied canvas to use as the query rect. | |
837 gfx::Rect canvas_bounds; | |
838 bool got_clip = canvas->GetClipBounds(&canvas_bounds); | |
839 DCHECK(got_clip) << "Failed to get clip bounds from the canvas!"; | |
840 | |
841 // Now query our bounds_tree_ for a set of damaged views that intersect | |
842 // our canvas bounds. | |
843 scoped_ptr<base::hash_set<intptr_t>> damaged_views( | |
844 new base::hash_set<intptr_t>); | |
845 bounds_tree_->AppendIntersectingRecords(canvas_bounds, damaged_views.get()); | |
846 CullSet paint_root_cull_set(damaged_views.Pass()); | |
847 PaintChildren(canvas, paint_root_cull_set); | |
828 } | 848 } |
829 | 849 |
830 void View::set_background(Background* b) { | 850 void View::set_background(Background* b) { |
831 background_.reset(b); | 851 background_.reset(b); |
832 } | 852 } |
833 | 853 |
834 void View::SetBorder(scoped_ptr<Border> b) { border_ = b.Pass(); } | 854 void View::SetBorder(scoped_ptr<Border> b) { border_ = b.Pass(); } |
835 | 855 |
836 ui::ThemeProvider* View::GetThemeProvider() const { | 856 ui::ThemeProvider* View::GetThemeProvider() const { |
837 const Widget* widget = GetWidget(); | 857 const Widget* widget = GetWidget(); |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1457 } else { | 1477 } else { |
1458 for (int i = 0, count = child_count(); i < count; ++i) { | 1478 for (int i = 0, count = child_count(); i < count; ++i) { |
1459 View* child = child_at(i); | 1479 View* child = child_at(i); |
1460 child->UpdateChildLayerBounds( | 1480 child->UpdateChildLayerBounds( |
1461 offset + gfx::Vector2d(child->GetMirroredX(), child->y())); | 1481 offset + gfx::Vector2d(child->GetMirroredX(), child->y())); |
1462 } | 1482 } |
1463 } | 1483 } |
1464 } | 1484 } |
1465 | 1485 |
1466 void View::OnPaintLayer(gfx::Canvas* canvas) { | 1486 void View::OnPaintLayer(gfx::Canvas* canvas) { |
1467 if (!layer() || !layer()->fills_bounds_opaquely()) | 1487 if (!layer()->fills_bounds_opaquely()) |
danakj
2015/03/25 20:52:36
I'm feeling more confident about this, so I remove
sky
2015/03/25 22:55:05
Agreed. If we wanted something it should be a DCHE
| |
1468 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); | 1488 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); |
1469 if (!visible_) | 1489 if (!visible_) |
1470 return; | 1490 return; |
1471 PaintCommon(canvas, CullSet()); | 1491 Paint(canvas, CullSet()); |
1472 } | 1492 } |
1473 | 1493 |
1474 void View::OnDelegatedFrameDamage( | 1494 void View::OnDelegatedFrameDamage( |
1475 const gfx::Rect& damage_rect_in_dip) { | 1495 const gfx::Rect& damage_rect_in_dip) { |
1476 } | 1496 } |
1477 | 1497 |
1478 void View::OnDeviceScaleFactorChanged(float device_scale_factor) { | 1498 void View::OnDeviceScaleFactorChanged(float device_scale_factor) { |
1479 snap_layer_to_pixel_boundary_ = | 1499 snap_layer_to_pixel_boundary_ = |
1480 (device_scale_factor - std::floor(device_scale_factor)) != 0.0f; | 1500 (device_scale_factor - std::floor(device_scale_factor)) != 0.0f; |
1481 SnapLayerToPixelBoundary(); | 1501 SnapLayerToPixelBoundary(); |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1744 SchedulePaint(); | 1764 SchedulePaint(); |
1745 } else if (parent_ && type == SCHEDULE_PAINT_SIZE_SAME) { | 1765 } else if (parent_ && type == SCHEDULE_PAINT_SIZE_SAME) { |
1746 // The compositor doesn't Draw() until something on screen changes, so | 1766 // The compositor doesn't Draw() until something on screen changes, so |
1747 // if our position changes but nothing is being animated on screen, then | 1767 // if our position changes but nothing is being animated on screen, then |
1748 // tell the compositor to redraw the scene. We know layer() exists due to | 1768 // tell the compositor to redraw the scene. We know layer() exists due to |
1749 // the above if clause. | 1769 // the above if clause. |
1750 layer()->ScheduleDraw(); | 1770 layer()->ScheduleDraw(); |
1751 } | 1771 } |
1752 } | 1772 } |
1753 | 1773 |
1754 void View::PaintCommon(gfx::Canvas* canvas, const CullSet& cull_set) { | |
1755 { | |
1756 // If the View we are about to paint requested the canvas to be flipped, we | |
1757 // should change the transform appropriately. | |
1758 // The canvas mirroring is undone once the View is done painting so that we | |
1759 // don't pass the canvas with the mirrored transform to Views that didn't | |
1760 // request the canvas to be flipped. | |
1761 gfx::ScopedCanvas scoped(canvas); | |
1762 if (FlipCanvasOnPaintForRTLUI()) { | |
1763 canvas->Translate(gfx::Vector2d(width(), 0)); | |
1764 canvas->Scale(-1, 1); | |
1765 } | |
1766 | |
1767 OnPaint(canvas); | |
1768 } | |
1769 | |
1770 PaintChildren(canvas, cull_set); | |
1771 } | |
1772 | |
1773 // Tree operations ------------------------------------------------------------- | 1774 // Tree operations ------------------------------------------------------------- |
1774 | 1775 |
1775 void View::DoRemoveChildView(View* view, | 1776 void View::DoRemoveChildView(View* view, |
1776 bool update_focus_cycle, | 1777 bool update_focus_cycle, |
1777 bool update_tool_tip, | 1778 bool update_tool_tip, |
1778 bool delete_removed_view, | 1779 bool delete_removed_view, |
1779 View* new_parent) { | 1780 View* new_parent) { |
1780 DCHECK(view); | 1781 DCHECK(view); |
1781 | 1782 |
1782 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); | 1783 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2474 // Message the RootView to do the drag and drop. That way if we're removed | 2475 // Message the RootView to do the drag and drop. That way if we're removed |
2475 // the RootView can detect it and avoid calling us back. | 2476 // the RootView can detect it and avoid calling us back. |
2476 gfx::Point widget_location(event.location()); | 2477 gfx::Point widget_location(event.location()); |
2477 ConvertPointToWidget(this, &widget_location); | 2478 ConvertPointToWidget(this, &widget_location); |
2478 widget->RunShellDrag(this, data, widget_location, drag_operations, source); | 2479 widget->RunShellDrag(this, data, widget_location, drag_operations, source); |
2479 // WARNING: we may have been deleted. | 2480 // WARNING: we may have been deleted. |
2480 return true; | 2481 return true; |
2481 } | 2482 } |
2482 | 2483 |
2483 } // namespace views | 2484 } // namespace views |
OLD | NEW |