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.
5 #include "chrome/browser/chromeos/ui/accessibility_focus_ring_layer.h"
7 #include "ash/display/display_controller.h"
10 #include "ui/aura/window.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/gfx/canvas.h"
18 // The number of pixels in the color gradient that fades to transparent.
19 const int kGradientWidth
= 6;
21 // The color of the focus ring. In the future this might be a parameter.
22 const int kFocusRingColorRed
= 247;
23 const int kFocusRingColorGreen
= 152;
24 const int kFocusRingColorBlue
= 58;
27 return ((x
> 0) ? 1 : (x
== 0) ? 0 : -1);
30 SkPath
MakePath(const AccessibilityFocusRing
& input_ring
,
32 const gfx::Vector2d
& offset
) {
33 AccessibilityFocusRing ring
= input_ring
;
35 for (int i
= 0; i
< 36; i
++) {
36 gfx::Point p
= input_ring
.points
[i
];
42 prev_index
= (prev_index
+ 35) % 36;
43 prev
= input_ring
.points
[prev_index
];
44 } while (prev
.x() == p
.x() && prev
.y() == p
.y() && prev_index
!= i
);
48 next_index
= (next_index
+ 1) % 36;
49 next
= input_ring
.points
[next_index
];
50 } while (next
.x() == p
.x() && next
.y() == p
.y() && next_index
!= i
);
52 gfx::Point delta0
= gfx::Point(sign(p
.x() - prev
.x()),
53 sign(p
.y() - prev
.y()));
54 gfx::Point delta1
= gfx::Point(sign(next
.x() - p
.x()),
55 sign(next
.y() - p
.y()));
57 if (delta0
.x() == delta1
.x() && delta0
.y() == delta1
.y()) {
58 ring
.points
[i
] = gfx::Point(
59 input_ring
.points
[i
].x() + outset
* delta0
.y(),
60 input_ring
.points
[i
].y() - outset
* delta0
.x());
62 ring
.points
[i
] = gfx::Point(
63 input_ring
.points
[i
].x() + ((i
+ 13) % 36 >= 18 ? outset
: -outset
),
64 input_ring
.points
[i
].y() + ((i
+ 4) % 36 >= 18 ? outset
: -outset
));
69 gfx::Point p0
= ring
.points
[0] - offset
;
70 path
.moveTo(SkIntToScalar(p0
.x()), SkIntToScalar(p0
.y()));
71 for (int i
= 0; i
< 12; i
++) {
72 int index0
= ((3 * i
) + 1) % 36;
73 int index1
= ((3 * i
) + 2) % 36;
74 int index2
= ((3 * i
) + 3) % 36;
75 gfx::Point p0
= ring
.points
[index0
] - offset
;
76 gfx::Point p1
= ring
.points
[index1
] - offset
;
77 gfx::Point p2
= ring
.points
[index2
] - offset
;
78 path
.lineTo(SkIntToScalar(p0
.x()), SkIntToScalar(p0
.y()));
79 path
.quadTo(SkIntToScalar(p1
.x()), SkIntToScalar(p1
.y()),
80 SkIntToScalar(p2
.x()), SkIntToScalar(p2
.y()));
88 AccessibilityFocusRingLayer::AccessibilityFocusRingLayer(
89 FocusRingLayerDelegate
* delegate
)
90 : FocusRingLayer(delegate
) {
93 AccessibilityFocusRingLayer::~AccessibilityFocusRingLayer() {}
95 void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing
& ring
) {
98 gfx::Rect bounds
= ring
.GetBounds();
99 int inset
= kGradientWidth
;
100 bounds
.Inset(-inset
, -inset
, -inset
, -inset
);
102 gfx::Display display
=
103 gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds
);
104 aura::Window
* root_window
= ash::Shell::GetInstance()->display_controller()
105 ->GetRootWindowForDisplayId(display
.id());
106 CreateOrUpdateLayer(root_window
, "AccessibilityFocusRing");
108 // Update the layer bounds.
109 layer()->SetBounds(bounds
);
112 void AccessibilityFocusRingLayer::OnPaintLayer(gfx::Canvas
* canvas
) {
113 gfx::Vector2d offset
= layer()->bounds().OffsetFromOrigin();
116 paint
.setFlags(SkPaint::kAntiAlias_Flag
);
117 paint
.setStyle(SkPaint::kStroke_Style
);
118 paint
.setStrokeWidth(2);
121 const int w
= kGradientWidth
;
122 for (int i
= 0; i
< w
; ++i
) {
125 255 * (w
- i
) * (w
- i
) / (w
* w
),
126 kFocusRingColorRed
, kFocusRingColorGreen
, kFocusRingColorBlue
));
127 path
= MakePath(ring_
, i
, offset
);
128 canvas
->DrawPath(path
, paint
);
132 } // namespace chromeos