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/android/compositor/decoration_title.h"
7 #include <android/bitmap.h>
9 #include "base/i18n/rtl.h"
10 #include "base/logging.h"
11 #include "cc/layers/layer.h"
12 #include "cc/layers/ui_resource_layer.h"
13 #include "chrome/browser/android/compositor/layer/throbber_layer.h"
14 #include "chrome/browser/android/compositor/layer_title_cache.h"
15 #include "content/public/browser/android/compositor.h"
16 #include "third_party/skia/include/core/SkColor.h"
17 #include "ui/android/resources/resource_manager.h"
18 #include "ui/android/resources/ui_resource_android.h"
19 #include "ui/base/l10n/l10n_util_android.h"
20 #include "ui/gfx/android/java_bitmap.h"
21 #include "ui/gfx/geometry/vector3d_f.h"
25 SkColor
GetThrobberColor(bool is_incognito
) {
26 // Blue-ish color for normal mode.
27 return is_incognito
? SK_ColorWHITE
: SkColorSetRGB(0x42, 0x85, 0xf4);
34 DecorationTitle::DecorationTitle(LayerTitleCache
* layer_title_cache
,
35 ui::ResourceManager
* resource_manager
,
36 int title_resource_id
,
37 int favicon_resource_id
,
38 int spinner_resource_id
,
39 int spinner_incognito_resource_id
,
41 int favicon_start_padding
,
42 int favicon_end_padding
,
45 : layer_(cc::Layer::Create(content::Compositor::LayerSettings())),
47 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
49 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
51 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
52 throbber_layer_(ThrobberLayer::Create(GetThrobberColor(is_incognito
))),
53 title_resource_id_(title_resource_id
),
54 favicon_resource_id_(favicon_resource_id
),
55 spinner_resource_id_(spinner_resource_id
),
56 spinner_incognito_resource_id_(spinner_resource_id
),
57 fade_width_(fade_width
),
58 favicon_start_padding_(favicon_start_padding
),
59 favicon_end_padding_(favicon_end_padding
),
60 is_incognito_(is_incognito
),
63 transform_(new gfx::Transform()),
64 resource_manager_(resource_manager
),
65 layer_title_cache_(layer_title_cache
) {
66 layer_
->AddChild(throbber_layer_
->layer());
67 layer_
->AddChild(layer_favicon_
);
68 layer_
->AddChild(layer_opaque_
);
69 layer_
->AddChild(layer_fade_
);
72 DecorationTitle::~DecorationTitle() {
73 layer_
->RemoveFromParent();
76 void DecorationTitle::SetResourceManager(
77 ui::ResourceManager
* resource_manager
) {
78 resource_manager_
= resource_manager
;
81 void DecorationTitle::PushPropertiesTo(int title_resource_id
,
82 int favicon_resource_id
,
84 int favicon_start_padding
,
85 int favicon_end_padding
,
88 title_resource_id_
= title_resource_id
;
89 favicon_resource_id_
= favicon_resource_id
;
90 is_incognito_
= is_incognito
;
91 throbber_layer_
->SetColor(GetThrobberColor(is_incognito
));
93 favicon_start_padding_
= favicon_start_padding
;
94 favicon_end_padding_
= favicon_end_padding
;
95 fade_width_
= fade_width
;
98 void DecorationTitle::SetUIResourceIds() {
99 ui::ResourceManager::Resource
* title_resource
=
100 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
102 if (title_resource
) {
103 layer_opaque_
->SetUIResourceId(title_resource
->ui_resource
->id());
104 layer_fade_
->SetUIResourceId(title_resource
->ui_resource
->id());
105 title_size_
= title_resource
->size
;
109 ui::ResourceManager::Resource
* favicon_resource
=
110 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
111 favicon_resource_id_
);
112 if (favicon_resource
) {
113 layer_favicon_
->SetUIResourceId(favicon_resource
->ui_resource
->id());
114 favicon_size_
= favicon_resource
->size
;
116 layer_favicon_
->SetUIResourceId(0);
118 layer_favicon_
->SetTransform(gfx::Transform());
119 layer_favicon_
->SetHideLayerAndSubtree(false);
120 throbber_layer_
->Hide();
122 layer_favicon_
->SetHideLayerAndSubtree(true);
123 throbber_layer_
->Show(base::Time::Now());
126 size_
= gfx::Size(title_size_
.width() + favicon_size_
.width(),
127 title_size_
.height());
130 void DecorationTitle::SetIsLoading(bool is_loading
) {
131 if (is_loading
!= is_loading_
) {
132 is_loading_
= is_loading
;
137 void DecorationTitle::UpdateThrobber() {
140 throbber_layer_
->UpdateThrobber(base::Time::Now());
143 void DecorationTitle::setOpacity(float opacity
) {
144 layer_opaque_
->SetOpacity(opacity
);
145 layer_favicon_
->SetOpacity(opacity
);
146 layer_fade_
->SetOpacity(opacity
);
147 throbber_layer_
->layer()->SetOpacity(opacity
);
150 void DecorationTitle::setBounds(const gfx::Size
& bounds
) {
151 layer_
->SetBounds(gfx::Size(bounds
.width(), size_
.height()));
153 if (bounds
.GetArea() == 0.f
) {
154 layer_
->SetHideLayerAndSubtree(true);
157 layer_
->SetHideLayerAndSubtree(false);
160 // Current implementation assumes there is always enough space
161 // to draw favicon and title fade.
163 // Note that favicon positon and title aligning depends on the system locale,
164 // l10n_util::IsLayoutRtl(), while title starting and fade out direction
165 // depends on the title text locale (DecorationTitle::is_rtl_).
167 bool sys_rtl
= l10n_util::IsLayoutRtl();
169 favicon_size_
.width() + favicon_start_padding_
+ favicon_end_padding_
;
170 int title_space
= std::max(0, bounds
.width() - favicon_space
- fade_width_
);
171 int fade_space
= std::max(0, bounds
.width() - favicon_space
- title_space
);
173 if (title_size_
.width() <= title_space
+ fade_space
)
174 title_space
+= fade_space
;
176 if (title_size_
.width() <= title_space
)
179 float favicon_offset_y
= (size_
.height() - favicon_size_
.height()) / 2.f
;
180 float title_offset_y
= (size_
.height() - title_size_
.height()) / 2.f
;
182 // Step 1. Place favicon.
183 int favicon_x
= favicon_start_padding_
;
185 favicon_x
= bounds
.width() - favicon_size_
.width() - favicon_start_padding_
;
187 layer_favicon_
->SetIsDrawable(true);
188 layer_favicon_
->SetBounds(favicon_size_
);
189 layer_favicon_
->SetPosition(gfx::PointF(favicon_x
, favicon_offset_y
));
190 throbber_layer_
->layer()->SetIsDrawable(true);
191 throbber_layer_
->layer()->SetBounds(favicon_size_
);
192 throbber_layer_
->layer()->SetPosition(
193 gfx::PointF(favicon_x
, favicon_offset_y
));
195 // Step 2. Place the opaque title component.
196 if (title_space
> 0.f
) {
197 // Calculate the title position and size, taking into account both
198 // system and title RTL.
199 int width
= std::min(title_space
, title_size_
.width());
200 int x_offset
= sys_rtl
? title_space
- width
: favicon_space
;
201 int x
= x_offset
+ (is_rtl_
? fade_space
: 0);
203 // Calculate the UV coordinates taking into account title RTL.
204 float width_percentage
= (float)width
/ title_size_
.width();
205 float u1
= is_rtl_
? 1.f
- width_percentage
: 0.f
;
206 float u2
= is_rtl_
? 1.f
: width_percentage
;
208 layer_opaque_
->SetIsDrawable(true);
209 layer_opaque_
->SetBounds(gfx::Size(width
, title_size_
.height()));
210 layer_opaque_
->SetPosition(gfx::PointF(x
, title_offset_y
));
211 layer_opaque_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
213 layer_opaque_
->SetIsDrawable(false);
216 // Step 3. Place the fade title component.
217 if (fade_space
> 0.f
) {
218 // Calculate the title position and size, taking into account both
219 // system and title RTL.
220 int x_offset
= sys_rtl
? 0 : favicon_space
;
221 int x
= x_offset
+ (is_rtl_
? 0 : title_space
);
222 float title_amt
= (float)title_space
/ title_size_
.width();
223 float fade_amt
= (float)fade_space
/ title_size_
.width();
225 // Calculate UV coordinates taking into account title RTL.
226 float u1
= is_rtl_
? 1.f
- title_amt
- fade_amt
: title_amt
;
227 float u2
= is_rtl_
? 1.f
- title_amt
: title_amt
+ fade_amt
;
229 // Calculate vertex alpha taking into account title RTL.
230 float max_alpha
= (float)fade_space
/ fade_width_
;
231 float a1
= is_rtl_
? 0.f
: max_alpha
;
232 float a2
= is_rtl_
? max_alpha
: 0.f
;
234 layer_fade_
->SetIsDrawable(true);
235 layer_fade_
->SetBounds(gfx::Size(fade_space
, title_size_
.height()));
236 layer_fade_
->SetPosition(gfx::PointF(x
, title_offset_y
));
237 layer_fade_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
238 layer_fade_
->SetVertexOpacity(a1
, a1
, a2
, a2
);
240 layer_fade_
->SetIsDrawable(false);
244 scoped_refptr
<cc::Layer
> DecorationTitle::layer() {
245 DCHECK(layer_
.get());
249 } // namespace android
250 } // namespace chrome