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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 const int kDefaultVerticalDragThreshold = 8; | 87 const int kDefaultVerticalDragThreshold = 8; |
88 | 88 |
89 // Returns the top view in |view|'s hierarchy. | 89 // Returns the top view in |view|'s hierarchy. |
90 const View* GetHierarchyRoot(const View* view) { | 90 const View* GetHierarchyRoot(const View* view) { |
91 const View* root = view; | 91 const View* root = view; |
92 while (root && root->parent()) | 92 while (root && root->parent()) |
93 root = root->parent(); | 93 root = root->parent(); |
94 return root; | 94 return root; |
95 } | 95 } |
96 | 96 |
| 97 /* |
| 98 gfx::Rect GetPixelBounds(const ui::PaintContext& parent_context, |
| 99 const gfx::Vector2d& child_origin, |
| 100 const gfx::Size& child_size, |
| 101 const gfx::Size& parent_pixel_size, |
| 102 const gfx::Rect& parent_bounds) { |
| 103 float dsf = parent_context.device_scale_factor(); |
| 104 |
| 105 int right = child_origin.x() + child_size.width(); |
| 106 int bottom = child_origin.y() + child_size.height(); |
| 107 |
| 108 int new_x = std::round(child_origin.x() * dsf); |
| 109 int new_y = std::round(child_origin.y() * dsf); |
| 110 |
| 111 int new_right; |
| 112 int new_bottom; |
| 113 |
| 114 if (right == parent_bounds.width()) { |
| 115 new_right = parent_pixel_size.width(); |
| 116 } else { |
| 117 new_right = std::round(right * dsf); |
| 118 } |
| 119 if (bottom == parent_bounds.height()) { |
| 120 new_bottom = parent_pixel_size.height(); |
| 121 } else { |
| 122 new_bottom = std::round(bottom * dsf); |
| 123 } |
| 124 return gfx::Rect(new_x, new_y, new_right - new_x, new_bottom - new_y); |
| 125 } |
| 126 */ |
| 127 |
97 } // namespace | 128 } // namespace |
98 | 129 |
99 namespace internal { | 130 namespace internal { |
100 | 131 |
101 #if DCHECK_IS_ON() | 132 #if DCHECK_IS_ON() |
102 class ScopedChildrenLock { | 133 class ScopedChildrenLock { |
103 public: | 134 public: |
104 explicit ScopedChildrenLock(const View* view) | 135 explicit ScopedChildrenLock(const View* view) |
105 : reset_(&view->iterating_, true) {} | 136 : reset_(&view->iterating_, true) {} |
106 ~ScopedChildrenLock() {} | 137 ~ScopedChildrenLock() {} |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 } else if (parent_) { | 852 } else if (parent_) { |
822 // Translate the requested paint rect to the parent's coordinate system | 853 // Translate the requested paint rect to the parent's coordinate system |
823 // then pass this notification up to the parent. | 854 // then pass this notification up to the parent. |
824 parent_->SchedulePaintInRect(ConvertRectToParent(rect)); | 855 parent_->SchedulePaintInRect(ConvertRectToParent(rect)); |
825 } | 856 } |
826 } | 857 } |
827 | 858 |
828 void View::Paint(const ui::PaintContext& parent_context) { | 859 void View::Paint(const ui::PaintContext& parent_context) { |
829 if (!ShouldPaint()) | 860 if (!ShouldPaint()) |
830 return; | 861 return; |
| 862 gfx::Vector2dF scale = parent_context.CanvasScale(); |
831 | 863 |
832 ui::PaintContext context(parent_context, GetPaintContextOffset()); | 864 gfx::Point offset_to_parent; |
| 865 if (!layer()) { |
| 866 // If the View has a layer() then it is a paint root. Otherwise, we need to |
| 867 // add the offset from the parent into the total offset from the paint root. |
| 868 DCHECK(parent() || origin() == gfx::Point()); |
| 869 offset_to_parent = GetMirroredPosition(); |
| 870 } |
| 871 |
| 872 gfx::Rect pixel_bounds = |
| 873 parent_context.GetPixelBounds(gfx::Rect(offset_to_parent, size())); |
| 874 /* |
| 875 LOG(ERROR) << "ParentPixelSize:" |
| 876 << "parent bounds=" << parent_bounds.ToString() |
| 877 << ", parent pixel=" << parent_pixel_size.ToString() |
| 878 << ", my size=" << size().ToString() |
| 879 << ", m pixel=" << pixel_bounds.ToString(); |
| 880 */ |
| 881 |
| 882 ui::PaintContext context(parent_context, GetPaintContextOffset(pixel_bounds)); |
| 883 context.UpdateSizeAndDSF(pixel_bounds.size(), size()); |
833 | 884 |
834 bool is_invalidated = true; | 885 bool is_invalidated = true; |
835 if (context.CanCheckInvalid()) { | 886 if (context.CanCheckInvalid()) { |
836 #if DCHECK_IS_ON() | 887 #if DCHECK_IS_ON() && 0 |
837 gfx::Vector2d offset; | 888 gfx::Vector2d offset; |
838 context.Visited(this); | 889 context.Visited(this); |
839 View* view = this; | 890 View* view = this; |
840 while (view->parent() && !view->layer()) { | 891 while (view->parent() && !view->layer()) { |
841 DCHECK(view->GetTransform().IsIdentity()); | 892 DCHECK(view->GetTransform().IsIdentity()); |
842 offset += view->GetMirroredPosition().OffsetFromOrigin(); | 893 offset += view->GetMirroredPosition().OffsetFromOrigin(); |
843 view = view->parent(); | 894 view = view->parent(); |
844 } | 895 } |
845 // The offset in the PaintContext should be the offset up to the paint root, | 896 // The offset in the PaintContext should be the offset up to the paint root, |
846 // which we compute and verify here. | 897 // which we compute and verify here. |
847 DCHECK_EQ(context.PaintOffset().x(), offset.x()); | 898 DCHECK_EQ(context.PaintOffset().x(), offset.x()); |
848 DCHECK_EQ(context.PaintOffset().y(), offset.y()); | 899 DCHECK_EQ(context.PaintOffset().y(), offset.y()); |
849 // The above loop will stop when |view| is the paint root, which should be | 900 // The above loop will stop when |view| is the paint root, which should be |
850 // the root of the current paint walk, as verified by storing the root in | 901 // the root of the current paint walk, as verified by storing the root in |
851 // the PaintContext. | 902 // the PaintContext. |
852 DCHECK_EQ(context.RootVisited(), view); | 903 DCHECK_EQ(context.RootVisited(), view); |
853 #endif | 904 #endif |
854 | 905 |
855 // If the View wasn't invalidated, don't waste time painting it, the output | 906 // If the View wasn't invalidated, don't waste time painting it, the output |
856 // would be culled. | 907 // would be culled. |
857 is_invalidated = context.IsRectInvalid(GetLocalBounds()); | 908 is_invalidated = context.IsRectInvalid(gfx::Rect(pixel_bounds.size())); |
858 } | 909 } |
859 | 910 |
860 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); | 911 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); |
861 | 912 |
862 // If the view is backed by a layer, it should paint with itself as the origin | 913 // If the view is backed by a layer, it should paint with itself as the origin |
863 // rather than relative to its parent. | 914 // rather than relative to its parent. |
864 // TODO(danakj): Rework clip and transform recorder usage here to use | 915 // TODO(danakj): Rework clip and transform recorder usage here to use |
865 // std::optional once we can do so. | 916 // std::optional once we can do so. |
866 ui::ClipRecorder clip_recorder(parent_context); | 917 ui::ClipRecorder clip_recorder(parent_context); |
867 if (!layer()) { | 918 if (!layer()) { |
868 // Set the clip rect to the bounds of this View, or |clip_path_| if it's | 919 // Set the clip rect to the bounds of this View, or |clip_path_| if it's |
869 // been set. Note that the X (or left) position we pass to ClipRect takes | 920 // been set. Note that the X (or left) position we pass to ClipRect takes |
870 // into consideration whether or not the View uses a right-to-left layout so | 921 // into consideration whether or not the View uses a right-to-left layout so |
871 // that we paint the View in its mirrored position if need be. | 922 // that we paint the View in its mirrored position if need be. |
872 if (clip_path_.isEmpty()) { | 923 if (clip_path_.isEmpty()) { |
873 clip_recorder.ClipRect(GetMirroredBounds()); | 924 clip_recorder.ClipRect(pixel_bounds); |
874 } else { | 925 } else { |
875 gfx::Path clip_path_in_parent = clip_path_; | 926 gfx::Path clip_path_in_parent = clip_path_; |
876 clip_path_in_parent.offset(GetMirroredX(), y()); | 927 clip_path_in_parent.offset(GetMirroredX(), y()); |
| 928 |
| 929 clip_path_in_parent.transform(SkMatrix::MakeScale( |
| 930 SkFloatToScalar(scale.x()), |
| 931 SkFloatToScalar(scale.y()))); |
877 clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent); | 932 clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent); |
878 } | 933 } |
879 } | 934 } |
880 | 935 |
881 ui::TransformRecorder transform_recorder(context); | 936 ui::TransformRecorder transform_recorder(context); |
882 SetupTransformRecorderForPainting(&transform_recorder); | 937 SetupTransformRecorderForPainting(&transform_recorder, |
| 938 GetPaintContextOffset(pixel_bounds)); |
883 | 939 |
884 // Note that the cache is not aware of the offset of the view | 940 // Note that the cache is not aware of the offset of the view |
885 // relative to the parent since painting is always done relative to | 941 // relative to the parent since painting is always done relative to |
886 // the top left of the individual view. | 942 // the top left of the individual view. |
887 if (is_invalidated || !paint_cache_.UseCache(context, size())) { | 943 if (is_invalidated || !paint_cache_.UseCache(context, pixel_bounds.size())) { |
888 ui::PaintRecorder recorder(context, size(), &paint_cache_); | 944 ui::PaintRecorder recorder(context, pixel_bounds.size(), &paint_cache_, |
| 945 true); |
889 gfx::Canvas* canvas = recorder.canvas(); | 946 gfx::Canvas* canvas = recorder.canvas(); |
890 gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width(), | 947 gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, pixel_bounds.width(), |
891 flip_canvas_on_paint_for_rtl_ui_); | 948 flip_canvas_on_paint_for_rtl_ui_); |
892 | 949 |
893 // Delegate painting the contents of the View to the virtual OnPaint method. | 950 // Delegate painting the contents of the View to the virtual OnPaint method. |
894 OnPaint(canvas); | 951 OnPaint(canvas); |
895 } | 952 } |
896 | 953 |
897 // View::Paint() recursion over the subtree. | 954 // View::Paint() recursion over the subtree. |
898 PaintChildren(context); | 955 PaintChildren(context); |
899 } | 956 } |
900 | 957 |
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1937 // Translate the requested paint rect to the parent's coordinate system | 1994 // Translate the requested paint rect to the parent's coordinate system |
1938 // then pass this notification up to the parent. | 1995 // then pass this notification up to the parent. |
1939 parent_->SchedulePaintInRect(ConvertRectToParent(GetLocalBounds())); | 1996 parent_->SchedulePaintInRect(ConvertRectToParent(GetLocalBounds())); |
1940 } | 1997 } |
1941 } | 1998 } |
1942 | 1999 |
1943 bool View::ShouldPaint() const { | 2000 bool View::ShouldPaint() const { |
1944 return visible_ && !size().IsEmpty(); | 2001 return visible_ && !size().IsEmpty(); |
1945 } | 2002 } |
1946 | 2003 |
1947 gfx::Vector2d View::GetPaintContextOffset() const { | 2004 gfx::Vector2d View::GetPaintContextOffset(const gfx::Rect& pixel_bounds) const { |
1948 // If the View has a layer() then it is a paint root. Otherwise, we need to | 2005 // If the View has a layer() then it is a paint root. Otherwise, we need to |
1949 // add the offset from the parent into the total offset from the paint root. | 2006 // add the offset from the parent into the total offset from the paint root. |
1950 DCHECK(layer() || parent() || origin() == gfx::Point()); | 2007 DCHECK(layer() || parent() || origin() == gfx::Point()); |
1951 return layer() ? gfx::Vector2d() : GetMirroredPosition().OffsetFromOrigin(); | 2008 if (layer()) |
| 2009 return gfx::Vector2d(); |
| 2010 int mirrored_x = GetMirroredXForRect(pixel_bounds); |
| 2011 return gfx::Vector2d(mirrored_x, pixel_bounds.y()); |
1952 } | 2012 } |
1953 | 2013 |
1954 void View::SetupTransformRecorderForPainting( | 2014 void View::SetupTransformRecorderForPainting( |
1955 ui::TransformRecorder* recorder) const { | 2015 ui::TransformRecorder* recorder, |
| 2016 gfx::Vector2d offset_from_parent) const { |
1956 // If the view is backed by a layer, it should paint with itself as the origin | 2017 // If the view is backed by a layer, it should paint with itself as the origin |
1957 // rather than relative to its parent. | 2018 // rather than relative to its parent.2 |
1958 if (layer()) | 2019 if (layer()) |
1959 return; | 2020 return; |
1960 | 2021 |
1961 // Translate the graphics such that 0,0 corresponds to where this View is | 2022 // Translate the graphics such that 0,0 corresponds to where this View is |
1962 // located relative to its parent. | 2023 // located relative to its parent. |
1963 gfx::Transform transform_from_parent; | 2024 gfx::Transform transform_from_parent; |
1964 gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin(); | |
1965 transform_from_parent.Translate(offset_from_parent.x(), | 2025 transform_from_parent.Translate(offset_from_parent.x(), |
1966 offset_from_parent.y()); | 2026 offset_from_parent.y()); |
1967 transform_from_parent.PreconcatTransform(GetTransform()); | |
1968 recorder->Transform(transform_from_parent); | 2027 recorder->Transform(transform_from_parent); |
1969 } | 2028 } |
1970 | 2029 |
1971 void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&), | 2030 void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&), |
1972 const ui::PaintContext& context) { | 2031 const ui::PaintContext& context) { |
1973 View::Views children = GetChildrenInZOrder(); | 2032 View::Views children = GetChildrenInZOrder(); |
1974 DCHECK_EQ(child_count(), static_cast<int>(children.size())); | 2033 DCHECK_EQ(child_count(), static_cast<int>(children.size())); |
1975 for (auto* child : children) { | 2034 for (auto* child : children) { |
1976 if (!child->layer()) | 2035 if (!child->layer()) |
1977 (child->*func)(context); | 2036 (child->*func)(context); |
1978 } | 2037 } |
1979 } | 2038 } |
1980 | 2039 |
1981 void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) { | 2040 void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) { |
1982 Paint(parent_context); | 2041 Paint(parent_context); |
1983 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 2042 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
1984 switches::kDrawViewBoundsRects)) | 2043 switches::kDrawViewBoundsRects)) |
1985 PaintDebugRects(parent_context); | 2044 PaintDebugRects(parent_context); |
1986 } | 2045 } |
1987 | 2046 |
1988 void View::PaintDebugRects(const ui::PaintContext& parent_context) { | 2047 void View::PaintDebugRects(const ui::PaintContext& parent_context) { |
1989 if (!ShouldPaint()) | 2048 if (!ShouldPaint()) |
1990 return; | 2049 return; |
1991 | 2050 |
1992 ui::PaintContext context(parent_context, GetPaintContextOffset()); | 2051 //const gfx::Size& parent_pixel_size = parent_context.pixel_size(); |
| 2052 //const gfx::Rect parent_bounds = parent() ? parent()->bounds() : bounds(); |
| 2053 gfx::Point offset_to_parent; |
| 2054 if (!layer()) { |
| 2055 // If the View has a layer() then it is a paint root. Otherwise, we need to |
| 2056 // add the offset from the parent into the total offset from the paint root. |
| 2057 DCHECK(parent() || origin() == gfx::Point()); |
| 2058 offset_to_parent = GetMirroredPosition(); |
| 2059 } |
| 2060 gfx::Rect pixel_bounds = parent_context.GetPixelBounds(gfx::Rect(offset_to_par
ent, size())); |
| 2061 ui::PaintContext context(parent_context, GetPaintContextOffset(pixel_bounds)); |
| 2062 context.UpdateSizeAndDSF(pixel_bounds.size(), size()); |
| 2063 |
1993 ui::TransformRecorder transform_recorder(context); | 2064 ui::TransformRecorder transform_recorder(context); |
1994 SetupTransformRecorderForPainting(&transform_recorder); | 2065 SetupTransformRecorderForPainting(&transform_recorder, |
| 2066 pixel_bounds.OffsetFromOrigin()); |
1995 | 2067 |
1996 RecursivePaintHelper(&View::PaintDebugRects, context); | 2068 RecursivePaintHelper(&View::PaintDebugRects, context); |
1997 | 2069 |
1998 // Draw outline rects for debugging. | 2070 // Draw outline rects for debugging. |
1999 ui::PaintRecorder recorder(context, size()); | 2071 ui::PaintRecorder recorder(context, pixel_bounds.size(), &paint_cache_, true); |
2000 gfx::Canvas* canvas = recorder.canvas(); | 2072 gfx::Canvas* canvas = recorder.canvas(); |
2001 const float scale = canvas->UndoDeviceScaleFactor(); | 2073 const float scale = canvas->UndoDeviceScaleFactor(); |
2002 gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale)); | 2074 gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale)); |
2003 outline_rect.Inset(0.5f, 0.5f); | 2075 outline_rect.Inset(0.5f, 0.5f); |
2004 const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0); | 2076 const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0); |
2005 canvas->DrawRect(outline_rect, color); | 2077 canvas->DrawRect(outline_rect, color); |
2006 } | 2078 } |
2007 | 2079 |
2008 // Tree operations ------------------------------------------------------------- | 2080 // Tree operations ------------------------------------------------------------- |
2009 | 2081 |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2664 // Message the RootView to do the drag and drop. That way if we're removed | 2736 // Message the RootView to do the drag and drop. That way if we're removed |
2665 // the RootView can detect it and avoid calling us back. | 2737 // the RootView can detect it and avoid calling us back. |
2666 gfx::Point widget_location(event.location()); | 2738 gfx::Point widget_location(event.location()); |
2667 ConvertPointToWidget(this, &widget_location); | 2739 ConvertPointToWidget(this, &widget_location); |
2668 widget->RunShellDrag(this, data, widget_location, drag_operations, source); | 2740 widget->RunShellDrag(this, data, widget_location, drag_operations, source); |
2669 // WARNING: we may have been deleted. | 2741 // WARNING: we may have been deleted. |
2670 return true; | 2742 return true; |
2671 } | 2743 } |
2672 | 2744 |
2673 } // namespace views | 2745 } // namespace views |
OLD | NEW |