OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h" | |
6 | |
7 #include "ash/shell.h" | |
8 #include "base/bind.h" | |
9 #include "ui/aura/window.h" | |
10 #include "ui/compositor/layer.h" | |
11 #include "ui/gfx/canvas.h" | |
12 | |
13 namespace chromeos { | |
14 | |
15 namespace { | |
16 | |
17 // The number of pixels in the color gradient that fades to transparent. | |
18 const int kGradientWidth = 10; | |
19 | |
20 // The color of the focus ring. In the future this might be a parameter. | |
21 const int kFocusRingColorRed = 247; | |
22 const int kFocusRingColorGreen = 152; | |
23 const int kFocusRingColorBlue = 58; | |
24 | |
25 int sign(int x) { | |
26 return ((x > 0) ? 1 : (x == 0) ? 0 : -1); | |
27 } | |
28 | |
29 SkPath MakePath(const AccessibilityFocusRing& input_ring, | |
30 int outset, | |
31 const gfx::Vector2d& offset) { | |
32 AccessibilityFocusRing ring = input_ring; | |
33 | |
34 for (int i = 0; i < 36; i++) { | |
35 gfx::Point p = input_ring.points[i]; | |
36 gfx::Point prev; | |
37 gfx::Point next; | |
38 | |
39 int prev_index = i; | |
40 do { | |
41 prev_index = (prev_index + 35) % 36; | |
42 prev = input_ring.points[prev_index]; | |
43 } while (prev.x() == p.x() && prev.y() == p.y()); | |
44 | |
45 int next_index = i; | |
46 do { | |
47 next_index = (next_index + 1) % 36; | |
48 next = input_ring.points[next_index]; | |
49 } while (next.x() == p.x() && next.y() == p.y()); | |
50 | |
51 gfx::Point delta0 = gfx::Point(sign(p.x() - prev.x()), | |
52 sign(p.y() - prev.y())); | |
53 gfx::Point delta1 = gfx::Point(sign(next.x() - p.x()), | |
54 sign(next.y() - p.y())); | |
55 | |
56 if (delta0.x() == delta1.x() && delta0.y() == delta1.y()) { | |
57 ring.points[i] = gfx::Point( | |
58 input_ring.points[i].x() + outset * delta0.y(), | |
59 input_ring.points[i].y() - outset * delta0.x()); | |
60 } else { | |
61 ring.points[i] = gfx::Point( | |
62 input_ring.points[i].x() + ((i + 13) % 36 >= 18 ? outset : -outset), | |
63 input_ring.points[i].y() + ((i + 4) % 36 >= 18 ? outset : -outset)); | |
64 } | |
65 } | |
66 | |
67 SkPath path; | |
68 gfx::Point p0 = ring.points[0] - offset; | |
69 path.moveTo(SkIntToScalar(p0.x()), SkIntToScalar(p0.y())); | |
70 for (int i = 0; i < 12; i++) { | |
71 int index0 = ((3 * i) + 1) % 36; | |
72 int index1 = ((3 * i) + 2) % 36; | |
73 int index2 = ((3 * i) + 3) % 36; | |
74 gfx::Point p0 = ring.points[index0] - offset; | |
75 gfx::Point p1 = ring.points[index1] - offset; | |
76 gfx::Point p2 = ring.points[index2] - offset; | |
77 path.lineTo(SkIntToScalar(p0.x()), SkIntToScalar(p0.y())); | |
78 path.quadTo(SkIntToScalar(p1.x()), SkIntToScalar(p1.y()), | |
79 SkIntToScalar(p2.x()), SkIntToScalar(p2.y())); | |
80 } | |
81 | |
82 return path; | |
83 } | |
84 | |
85 } // namespace | |
86 | |
87 AccessibilityFocusRingLayer::AccessibilityFocusRingLayer( | |
88 FocusRingLayerDelegate* delegate) | |
89 : FocusRingLayer(delegate) { | |
90 } | |
91 | |
92 AccessibilityFocusRingLayer::~AccessibilityFocusRingLayer() {} | |
93 | |
94 void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing& ring) { | |
95 ring_ = ring; | |
96 | |
97 gfx::Rect bounds = ring.GetBounds(); | |
98 int inset = kGradientWidth; | |
99 bounds.Inset(-inset, -inset, -inset, -inset); | |
100 | |
101 if (!layer_) { | |
102 aura::Window* root_window = ash::Shell::GetPrimaryRootWindow(); | |
xiyuan
2014/09/11 03:57:45
Primary root window might not always be right. We
dmazzoni
2014/09/11 21:44:39
Great! I knew this needed to be done but wasn't su
| |
103 ui::Layer* root_layer = root_window->layer(); | |
104 layer_.reset(new ui::Layer(ui::LAYER_TEXTURED)); | |
105 layer_->set_name("AccessibilityFocusRing"); | |
106 layer_->set_delegate(this); | |
107 layer_->SetFillsBoundsOpaquely(false); | |
108 root_layer->Add(layer_.get()); | |
109 } | |
110 | |
111 // Keep moving it to the top in case new layers have been added | |
112 // since we created this layer. | |
113 layer_->parent()->StackAtTop(layer_.get()); | |
114 | |
115 // Update the layer bounds. | |
116 layer_->SetBounds(bounds); | |
117 } | |
118 | |
119 void AccessibilityFocusRingLayer::OnPaintLayer(gfx::Canvas* canvas) { | |
120 gfx::Vector2d offset = layer_->bounds().OffsetFromOrigin(); | |
121 | |
122 SkPaint paint; | |
123 paint.setFlags(SkPaint::kAntiAlias_Flag); | |
124 paint.setStyle(SkPaint::kStroke_Style); | |
125 paint.setStrokeWidth(2); | |
126 | |
127 SkPath path; | |
128 for (int i = 0; i < kGradientWidth; i++) { | |
129 paint.setColor( | |
130 SkColorSetARGBMacro( | |
131 255 - (255 * i / kGradientWidth), | |
132 kFocusRingColorRed, kFocusRingColorGreen, kFocusRingColorBlue)); | |
133 path = MakePath(ring_, i, offset); | |
134 canvas->DrawPath(path, paint); | |
135 } | |
136 } | |
137 | |
138 } // namespace chromeos | |
OLD | NEW |