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/compositor/paint_recorder.h"
13 #include "ui/gfx/canvas.h"
19 // The number of pixels in the color gradient that fades to transparent.
20 const int kGradientWidth
= 6;
22 // The color of the focus ring. In the future this might be a parameter.
23 const int kFocusRingColorRed
= 247;
24 const int kFocusRingColorGreen
= 152;
25 const int kFocusRingColorBlue
= 58;
28 return ((x
> 0) ? 1 : (x
== 0) ? 0 : -1);
31 SkPath
MakePath(const AccessibilityFocusRing
& input_ring
,
33 const gfx::Vector2d
& offset
) {
34 AccessibilityFocusRing ring
= input_ring
;
36 for (int i
= 0; i
< 36; i
++) {
37 gfx::Point p
= input_ring
.points
[i
];
43 prev_index
= (prev_index
+ 35) % 36;
44 prev
= input_ring
.points
[prev_index
];
45 } while (prev
.x() == p
.x() && prev
.y() == p
.y() && prev_index
!= i
);
49 next_index
= (next_index
+ 1) % 36;
50 next
= input_ring
.points
[next_index
];
51 } while (next
.x() == p
.x() && next
.y() == p
.y() && next_index
!= i
);
53 gfx::Point delta0
= gfx::Point(sign(p
.x() - prev
.x()),
54 sign(p
.y() - prev
.y()));
55 gfx::Point delta1
= gfx::Point(sign(next
.x() - p
.x()),
56 sign(next
.y() - p
.y()));
58 if (delta0
.x() == delta1
.x() && delta0
.y() == delta1
.y()) {
59 ring
.points
[i
] = gfx::Point(
60 input_ring
.points
[i
].x() + outset
* delta0
.y(),
61 input_ring
.points
[i
].y() - outset
* delta0
.x());
63 ring
.points
[i
] = gfx::Point(
64 input_ring
.points
[i
].x() + ((i
+ 13) % 36 >= 18 ? outset
: -outset
),
65 input_ring
.points
[i
].y() + ((i
+ 4) % 36 >= 18 ? outset
: -outset
));
70 gfx::Point p0
= ring
.points
[0] - offset
;
71 path
.moveTo(SkIntToScalar(p0
.x()), SkIntToScalar(p0
.y()));
72 for (int i
= 0; i
< 12; i
++) {
73 int index0
= ((3 * i
) + 1) % 36;
74 int index1
= ((3 * i
) + 2) % 36;
75 int index2
= ((3 * i
) + 3) % 36;
76 gfx::Point p0
= ring
.points
[index0
] - offset
;
77 gfx::Point p1
= ring
.points
[index1
] - offset
;
78 gfx::Point p2
= ring
.points
[index2
] - offset
;
79 path
.lineTo(SkIntToScalar(p0
.x()), SkIntToScalar(p0
.y()));
80 path
.quadTo(SkIntToScalar(p1
.x()), SkIntToScalar(p1
.y()),
81 SkIntToScalar(p2
.x()), SkIntToScalar(p2
.y()));
89 AccessibilityFocusRingLayer::AccessibilityFocusRingLayer(
90 FocusRingLayerDelegate
* delegate
)
91 : FocusRingLayer(delegate
) {
94 AccessibilityFocusRingLayer::~AccessibilityFocusRingLayer() {}
96 void AccessibilityFocusRingLayer::Set(const AccessibilityFocusRing
& ring
) {
99 gfx::Rect bounds
= ring
.GetBounds();
100 int inset
= kGradientWidth
;
101 bounds
.Inset(-inset
, -inset
, -inset
, -inset
);
103 gfx::Display display
=
104 gfx::Screen::GetNativeScreen()->GetDisplayMatching(bounds
);
105 aura::Window
* root_window
= ash::Shell::GetInstance()->display_controller()
106 ->GetRootWindowForDisplayId(display
.id());
107 CreateOrUpdateLayer(root_window
, "AccessibilityFocusRing");
109 // Update the layer bounds.
110 layer()->SetBounds(bounds
);
113 void AccessibilityFocusRingLayer::OnPaintLayer(
114 const ui::PaintContext
& context
) {
115 ui::PaintRecorder
recorder(context
, layer()->size());
118 paint
.setFlags(SkPaint::kAntiAlias_Flag
);
119 paint
.setStyle(SkPaint::kStroke_Style
);
120 paint
.setStrokeWidth(2);
123 gfx::Vector2d offset
= layer()->bounds().OffsetFromOrigin();
124 const int w
= kGradientWidth
;
125 for (int i
= 0; i
< w
; ++i
) {
128 255 * (w
- i
) * (w
- i
) / (w
* w
),
129 kFocusRingColorRed
, kFocusRingColorGreen
, kFocusRingColorBlue
));
130 path
= MakePath(ring_
, i
, offset
);
131 recorder
.canvas()->DrawPath(path
, paint
);
135 } // namespace chromeos