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 "ui/android/resources/resource_manager.h"
15 #include "ui/android/resources/ui_resource_android.h"
16 #include "ui/base/l10n/l10n_util_android.h"
17 #include "ui/gfx/android/java_bitmap.h"
18 #include "ui/gfx/geometry/vector3d_f.h"
23 DecorationTitle::DecorationTitle(LayerTitleCache
* layer_title_cache
,
24 ui::ResourceManager
* resource_manager
,
25 int title_resource_id
,
26 int favicon_resource_id
,
27 int spinner_resource_id
,
28 int spinner_incognito_resource_id
,
30 int favicon_start_padding
,
31 int favicon_end_padding
,
34 : layer_(cc::Layer::Create()),
35 layer_opaque_(cc::UIResourceLayer::Create()),
36 layer_fade_(cc::UIResourceLayer::Create()),
37 layer_favicon_(cc::UIResourceLayer::Create()),
38 title_resource_id_(title_resource_id
),
39 favicon_resource_id_(favicon_resource_id
),
40 spinner_resource_id_(spinner_resource_id
),
41 spinner_incognito_resource_id_(spinner_resource_id
),
42 fade_width_(fade_width
),
44 favicon_start_padding_(favicon_start_padding
),
45 favicon_end_padding_(favicon_end_padding
),
46 is_incognito_(is_incognito
),
49 transform_(new gfx::Transform()),
50 resource_manager_(resource_manager
),
51 layer_title_cache_(layer_title_cache
) {
52 layer_
->AddChild(layer_favicon_
);
53 layer_
->AddChild(layer_opaque_
);
54 layer_
->AddChild(layer_fade_
);
57 DecorationTitle::~DecorationTitle() {
58 layer_
->RemoveFromParent();
61 void DecorationTitle::SetResourceManager(
62 ui::ResourceManager
* resource_manager
) {
63 resource_manager_
= resource_manager
;
66 void DecorationTitle::Update(int title_resource_id
,
67 int favicon_resource_id
,
69 int favicon_start_padding
,
70 int favicon_end_padding
,
73 title_resource_id_
= title_resource_id
;
74 favicon_resource_id_
= favicon_resource_id
;
75 is_incognito_
= is_incognito
;
77 favicon_start_padding_
= favicon_start_padding
;
78 favicon_end_padding_
= favicon_end_padding
;
79 fade_width_
= fade_width
;
82 void DecorationTitle::SetUIResourceIds() {
83 ui::ResourceManager::Resource
* title_resource
=
84 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
87 layer_opaque_
->SetUIResourceId(title_resource
->ui_resource
->id());
88 layer_fade_
->SetUIResourceId(title_resource
->ui_resource
->id());
89 title_size_
= title_resource
->size
;
93 ui::ResourceManager::Resource
* favicon_resource
=
94 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_DYNAMIC_BITMAP
,
95 favicon_resource_id_
);
96 if (favicon_resource
) {
97 layer_favicon_
->SetUIResourceId(favicon_resource
->ui_resource
->id());
98 favicon_size_
= favicon_resource
->size
;
100 layer_favicon_
->SetUIResourceId(0);
102 layer_favicon_
->SetTransform(gfx::Transform());
105 is_incognito_
? spinner_incognito_resource_id_
: spinner_resource_id_
;
107 ui::ResourceManager::Resource
* spinner_resource
=
108 resource_manager_
->GetResource(ui::ANDROID_RESOURCE_TYPE_STATIC
,
111 if (spinner_resource
)
112 layer_favicon_
->SetUIResourceId(spinner_resource
->ui_resource
->id());
114 // Rotate about the center of the layer.
115 layer_favicon_
->SetTransformOrigin(
116 gfx::Point3F(favicon_size_
.width() / 2, favicon_size_
.height() / 2, 0));
119 size_
= gfx::Size(title_size_
.width() + favicon_size_
.width(),
120 title_size_
.height());
123 void DecorationTitle::SetIsLoading(bool is_loading
) {
124 if (is_loading
!= is_loading_
) {
125 is_loading_
= is_loading
;
130 void DecorationTitle::SetSpinnerRotation(float rotation
) {
133 float diff
= rotation
- spinner_rotation_
;
134 spinner_rotation_
= rotation
;
136 transform_
->RotateAboutZAxis(diff
);
138 layer_favicon_
->SetTransform(*transform_
.get());
141 void DecorationTitle::setOpacity(float opacity
) {
142 layer_opaque_
->SetOpacity(opacity
);
143 layer_favicon_
->SetOpacity(opacity
);
144 layer_fade_
->SetOpacity(opacity
);
147 void DecorationTitle::setBounds(const gfx::Size
& bounds
) {
148 layer_
->SetBounds(gfx::Size(bounds
.width(), size_
.height()));
150 if (bounds
.GetArea() == 0.f
) {
151 layer_
->SetHideLayerAndSubtree(true);
154 layer_
->SetHideLayerAndSubtree(false);
157 // Current implementation assumes there is always enough space
158 // to draw favicon and title fade.
160 // Note that favicon positon and title aligning depends on the system locale,
161 // l10n_util::IsLayoutRtl(), while title starting and fade out direction
162 // depends on the title text locale (DecorationTitle::is_rtl_).
164 bool sys_rtl
= l10n_util::IsLayoutRtl();
166 favicon_size_
.width() + favicon_start_padding_
+ favicon_end_padding_
;
167 int title_space
= std::max(0, bounds
.width() - favicon_space
- fade_width_
);
168 int fade_space
= std::max(0, bounds
.width() - favicon_space
- title_space
);
170 if (title_size_
.width() <= title_space
+ fade_space
)
171 title_space
+= fade_space
;
173 if (title_size_
.width() <= title_space
)
176 float favicon_offset_y
= (size_
.height() - favicon_size_
.height()) / 2.f
;
177 float title_offset_y
= (size_
.height() - title_size_
.height()) / 2.f
;
179 // Step 1. Place favicon.
180 int favicon_x
= favicon_start_padding_
;
182 favicon_x
= bounds
.width() - favicon_size_
.width() - favicon_start_padding_
;
184 layer_favicon_
->SetIsDrawable(true);
185 layer_favicon_
->SetBounds(favicon_size_
);
186 layer_favicon_
->SetPosition(gfx::PointF(favicon_x
, favicon_offset_y
));
188 // Step 2. Place the opaque title component.
189 if (title_space
> 0.f
) {
190 // Calculate the title position and size, taking into account both
191 // system and title RTL.
192 int width
= std::min(title_space
, title_size_
.width());
193 int x_offset
= sys_rtl
? title_space
- width
: favicon_space
;
194 int x
= x_offset
+ (is_rtl_
? fade_space
: 0);
196 // Calculate the UV coordinates taking into account title RTL.
197 float width_percentage
= (float)width
/ title_size_
.width();
198 float u1
= is_rtl_
? 1.f
- width_percentage
: 0.f
;
199 float u2
= is_rtl_
? 1.f
: width_percentage
;
201 layer_opaque_
->SetIsDrawable(true);
202 layer_opaque_
->SetBounds(gfx::Size(width
, title_size_
.height()));
203 layer_opaque_
->SetPosition(gfx::PointF(x
, title_offset_y
));
204 layer_opaque_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
206 layer_opaque_
->SetIsDrawable(false);
209 // Step 3. Place the fade title component.
210 if (fade_space
> 0.f
) {
211 // Calculate the title position and size, taking into account both
212 // system and title RTL.
213 int x_offset
= sys_rtl
? 0 : favicon_space
;
214 int x
= x_offset
+ (is_rtl_
? 0 : title_space
);
215 float title_amt
= (float)title_space
/ title_size_
.width();
216 float fade_amt
= (float)fade_space
/ title_size_
.width();
218 // Calculate UV coordinates taking into account title RTL.
219 float u1
= is_rtl_
? 1.f
- title_amt
- fade_amt
: title_amt
;
220 float u2
= is_rtl_
? 1.f
- title_amt
: title_amt
+ fade_amt
;
222 // Calculate vertex alpha taking into account title RTL.
223 float max_alpha
= (float)fade_space
/ fade_width_
;
224 float a1
= is_rtl_
? 0.f
: max_alpha
;
225 float a2
= is_rtl_
? max_alpha
: 0.f
;
227 layer_fade_
->SetIsDrawable(true);
228 layer_fade_
->SetBounds(gfx::Size(fade_space
, title_size_
.height()));
229 layer_fade_
->SetPosition(gfx::PointF(x
, title_offset_y
));
230 layer_fade_
->SetUV(gfx::PointF(u1
, 0.f
), gfx::PointF(u2
, 1.f
));
231 layer_fade_
->SetVertexOpacity(a1
, a1
, a2
, a2
);
233 layer_fade_
->SetIsDrawable(false);
237 scoped_refptr
<cc::Layer
> DecorationTitle::layer() {
238 DCHECK(layer_
.get());
242 } // namespace android
243 } // namespace chrome