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_title_cache.h"
14 #include "content/public/browser/android/compositor.h"
15 #include "ui/android/resources/resource_manager.h"
16 #include "ui/android/resources/ui_resource_android.h"
17 #include "ui/base/l10n/l10n_util_android.h"
18 #include "ui/gfx/android/java_bitmap.h"
19 #include "ui/gfx/geometry/vector3d_f.h"
24 DecorationTitle::DecorationTitle(LayerTitleCache
* layer_title_cache
,
25 ui::ResourceManager
* resource_manager
,
26 int title_resource_id
,
27 int favicon_resource_id
,
28 int spinner_resource_id
,
29 int spinner_incognito_resource_id
,
31 int favicon_start_padding
,
32 int favicon_end_padding
,
35 : layer_(cc::Layer::Create(content::Compositor::LayerSettings())),
37 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
39 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
41 cc::UIResourceLayer::Create(content::Compositor::LayerSettings())),
42 title_resource_id_(title_resource_id
),
43 favicon_resource_id_(favicon_resource_id
),
44 spinner_resource_id_(spinner_resource_id
),
45 spinner_incognito_resource_id_(spinner_resource_id
),
46 fade_width_(fade_width
),
48 favicon_start_padding_(favicon_start_padding
),
49 favicon_end_padding_(favicon_end_padding
),
50 is_incognito_(is_incognito
),
53 transform_(new gfx::Transform()),
54 resource_manager_(resource_manager
),
55 layer_title_cache_(layer_title_cache
) {
56 layer_
->AddChild(layer_favicon_
);
57 layer_
->AddChild(layer_opaque_
);
58 layer_
->AddChild(layer_fade_
);
61 DecorationTitle::~DecorationTitle() {
62 layer_
->RemoveFromParent();
65 void DecorationTitle::SetResourceManager(
66 ui::ResourceManager
* resource_manager
) {
67 resource_manager_
= resource_manager
;
70 void DecorationTitle::Update(int title_resource_id
,
71 int favicon_resource_id
,
73 int favicon_start_padding
,
74 int favicon_end_padding
,
77 title_resource_id_
= title_resource_id
;
78 favicon_resource_id_
= favicon_resource_id
;
79 is_incognito_
= is_incognito
;
81 favicon_start_padding_
= favicon_start_padding
;
82 favicon_end_padding_
= favicon_end_padding
;
83 fade_width_
= fade_width
;
86 void DecorationTitle::SetUIResourceIds() {
87 ui::ResourceManager::Resource
* title_resource
=
88 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
91 layer_opaque_
->SetUIResourceId(title_resource
->ui_resource
->id());
92 layer_fade_
->SetUIResourceId(title_resource
->ui_resource
->id());
93 title_size_
= title_resource
->size
;
97 ui::ResourceManager::Resource
* favicon_resource
=
98 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
99 favicon_resource_id_
);
100 if (favicon_resource
) {
101 layer_favicon_
->SetUIResourceId(favicon_resource
->ui_resource
->id());
102 favicon_size_
= favicon_resource
->size
;
104 layer_favicon_
->SetUIResourceId(0);
106 layer_favicon_
->SetTransform(gfx::Transform());
109 is_incognito_
? spinner_incognito_resource_id_
: spinner_resource_id_
;
111 ui::ResourceManager::Resource
* spinner_resource
=
112 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_STATIC
,
115 if (spinner_resource
)
116 layer_favicon_
->SetUIResourceId(spinner_resource
->ui_resource
->id());
118 // Rotate about the center of the layer.
119 layer_favicon_
->SetTransformOrigin(
120 gfx::Point3F(favicon_size_
.width() / 2, favicon_size_
.height() / 2, 0));
123 size_
= gfx::Size(title_size_
.width() + favicon_size_
.width(),
124 title_size_
.height());
127 void DecorationTitle::SetIsLoading(bool is_loading
) {
128 if (is_loading
!= is_loading_
) {
129 is_loading_
= is_loading
;
134 void DecorationTitle::SetSpinnerRotation(float rotation
) {
137 float diff
= rotation
- spinner_rotation_
;
138 spinner_rotation_
= rotation
;
140 transform_
->RotateAboutZAxis(diff
);
142 layer_favicon_
->SetTransform(*transform_
.get());
145 void DecorationTitle::setOpacity(float opacity
) {
146 layer_opaque_
->SetOpacity(opacity
);
147 layer_favicon_
->SetOpacity(opacity
);
148 layer_fade_
->SetOpacity(opacity
);
151 void DecorationTitle::setBounds(const gfx::Size
& bounds
) {
152 layer_
->SetBounds(gfx::Size(bounds
.width(), size_
.height()));
154 if (bounds
.GetArea() == 0.f
) {
155 layer_
->SetHideLayerAndSubtree(true);
158 layer_
->SetHideLayerAndSubtree(false);
161 // Current implementation assumes there is always enough space
162 // to draw favicon and title fade.
164 // Note that favicon positon and title aligning depends on the system locale,
165 // l10n_util::IsLayoutRtl(), while title starting and fade out direction
166 // depends on the title text locale (DecorationTitle::is_rtl_).
168 bool sys_rtl
= l10n_util::IsLayoutRtl();
170 favicon_size_
.width() + favicon_start_padding_
+ favicon_end_padding_
;
171 int title_space
= std::max(0, bounds
.width() - favicon_space
- fade_width_
);
172 int fade_space
= std::max(0, bounds
.width() - favicon_space
- title_space
);
174 if (title_size_
.width() <= title_space
+ fade_space
)
175 title_space
+= fade_space
;
177 if (title_size_
.width() <= title_space
)
180 float favicon_offset_y
= (size_
.height() - favicon_size_
.height()) / 2.f
;
181 float title_offset_y
= (size_
.height() - title_size_
.height()) / 2.f
;
183 // Step 1. Place favicon.
184 int favicon_x
= favicon_start_padding_
;
186 favicon_x
= bounds
.width() - favicon_size_
.width() - favicon_start_padding_
;
188 layer_favicon_
->SetIsDrawable(true);
189 layer_favicon_
->SetBounds(favicon_size_
);
190 layer_favicon_
->SetPosition(gfx::PointF(favicon_x
, favicon_offset_y
));
192 // Step 2. Place the opaque title component.
193 if (title_space
> 0.f
) {
194 // Calculate the title position and size, taking into account both
195 // system and title RTL.
196 int width
= std::min(title_space
, title_size_
.width());
197 int x_offset
= sys_rtl
? title_space
- width
: favicon_space
;
198 int x
= x_offset
+ (is_rtl_
? fade_space
: 0);
200 // Calculate the UV coordinates taking into account title RTL.
201 float width_percentage
= (float)width
/ title_size_
.width();
202 float u1
= is_rtl_
? 1.f
- width_percentage
: 0.f
;
203 float u2
= is_rtl_
? 1.f
: width_percentage
;
205 layer_opaque_
->SetIsDrawable(true);
206 layer_opaque_
->SetBounds(gfx::Size(width
, title_size_
.height()));
207 layer_opaque_
->SetPosition(gfx::PointF(x
, title_offset_y
));
208 layer_opaque_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
210 layer_opaque_
->SetIsDrawable(false);
213 // Step 3. Place the fade title component.
214 if (fade_space
> 0.f
) {
215 // Calculate the title position and size, taking into account both
216 // system and title RTL.
217 int x_offset
= sys_rtl
? 0 : favicon_space
;
218 int x
= x_offset
+ (is_rtl_
? 0 : title_space
);
219 float title_amt
= (float)title_space
/ title_size_
.width();
220 float fade_amt
= (float)fade_space
/ title_size_
.width();
222 // Calculate UV coordinates taking into account title RTL.
223 float u1
= is_rtl_
? 1.f
- title_amt
- fade_amt
: title_amt
;
224 float u2
= is_rtl_
? 1.f
- title_amt
: title_amt
+ fade_amt
;
226 // Calculate vertex alpha taking into account title RTL.
227 float max_alpha
= (float)fade_space
/ fade_width_
;
228 float a1
= is_rtl_
? 0.f
: max_alpha
;
229 float a2
= is_rtl_
? max_alpha
: 0.f
;
231 layer_fade_
->SetIsDrawable(true);
232 layer_fade_
->SetBounds(gfx::Size(fade_space
, title_size_
.height()));
233 layer_fade_
->SetPosition(gfx::PointF(x
, title_offset_y
));
234 layer_fade_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
235 layer_fade_
->SetVertexOpacity(a1
, a1
, a2
, a2
);
237 layer_fade_
->SetIsDrawable(false);
241 scoped_refptr
<cc::Layer
> DecorationTitle::layer() {
242 DCHECK(layer_
.get());
246 } // namespace android
247 } // namespace chrome