1 // Copyright 2013 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/ui/app_list/fast_show_pickler.h"
7 #include "third_party/skia/include/core/SkBitmap.h"
8 #include "ui/app_list/app_list_item.h"
9 #include "ui/gfx/image/image_skia_rep.h"
13 using app_list::AppListItem
;
14 using app_list::AppListModel
;
16 // These have the same meaning as SkBitmap::Config. Reproduced here to insure
17 // against their value changing in Skia. If the order of these changes kVersion
18 // should be incremented.
28 bool FormatToConfig(ImageFormat format
, SkBitmap::Config
* out
) {
31 *out
= SkBitmap::kNo_Config
;
34 *out
= SkBitmap::kA8_Config
;
37 *out
= SkBitmap::kIndex8_Config
;
40 *out
= SkBitmap::kRGB_565_Config
;
43 *out
= SkBitmap::kARGB_4444_Config
;
46 *out
= SkBitmap::kARGB_8888_Config
;
48 default: return false;
53 bool ConfigToFormat(SkBitmap::Config config
, ImageFormat
* out
) {
55 case SkBitmap::kNo_Config
:
58 case SkBitmap::kA8_Config
:
61 case SkBitmap::kIndex8_Config
:
64 case SkBitmap::kRGB_565_Config
:
67 case SkBitmap::kARGB_4444_Config
:
70 case SkBitmap::kARGB_8888_Config
:
73 default: return false;
78 bool PickleImage(Pickle
* pickle
, const gfx::ImageSkia
& image
) {
79 std::vector
<gfx::ImageSkiaRep
> reps(image
.image_reps());
80 pickle
->WriteInt(static_cast<int>(reps
.size()));
81 for (std::vector
<gfx::ImageSkiaRep
>::const_iterator it
= reps
.begin();
82 it
!= reps
.end(); ++it
) {
83 pickle
->WriteFloat(it
->scale());
84 pickle
->WriteInt(it
->pixel_width());
85 pickle
->WriteInt(it
->pixel_height());
86 ImageFormat format
= NONE
;
87 if (!ConfigToFormat(it
->sk_bitmap().getConfig(), &format
))
89 pickle
->WriteInt(static_cast<int>(format
));
90 int size
= static_cast<int>(it
->sk_bitmap().getSafeSize());
91 pickle
->WriteInt(size
);
92 SkBitmap bitmap
= it
->sk_bitmap();
93 SkAutoLockPixels
lock(bitmap
);
94 pickle
->WriteBytes(bitmap
.getPixels(), size
);
99 bool UnpickleImage(PickleIterator
* it
, gfx::ImageSkia
* out
) {
101 if (!it
->ReadInt(&rep_count
))
104 gfx::ImageSkia result
;
105 for (int i
= 0; i
< rep_count
; ++i
) {
107 if (!it
->ReadFloat(&scale
))
111 if (!it
->ReadInt(&width
))
115 if (!it
->ReadInt(&height
))
119 if (!it
->ReadInt(&format_int
))
121 ImageFormat format
= static_cast<ImageFormat
>(format_int
);
122 SkBitmap::Config config
= SkBitmap::kNo_Config
;
123 if (!FormatToConfig(format
, &config
))
127 if (!it
->ReadInt(&size
))
130 const char* pixels
= NULL
;
131 if (!it
->ReadBytes(&pixels
, size
))
135 bitmap
.setConfig(static_cast<SkBitmap::Config
>(config
), width
, height
);
136 if (!bitmap
.allocPixels())
139 SkAutoLockPixels
lock(bitmap
);
140 memcpy(bitmap
.getPixels(), pixels
, bitmap
.getSize());
142 result
.AddRepresentation(gfx::ImageSkiaRep(bitmap
, scale
));
149 scoped_ptr
<AppListItem
> UnpickleAppListItem(PickleIterator
* it
) {
151 if (!it
->ReadString(&id
))
152 return scoped_ptr
<AppListItem
>();
153 scoped_ptr
<AppListItem
> result(new AppListItem(id
));
155 if (!it
->ReadString(&title
))
156 return scoped_ptr
<AppListItem
>();
157 std::string full_name
;
158 if (!it
->ReadString(&full_name
))
159 return scoped_ptr
<AppListItem
>();
160 result
->SetTitleAndFullName(title
, full_name
);
161 bool has_shadow
= false;
162 if (!it
->ReadBool(&has_shadow
))
163 return scoped_ptr
<AppListItem
>();
165 if (!UnpickleImage(it
, &icon
))
166 return scoped_ptr
<AppListItem
>();
167 result
->SetIcon(icon
, has_shadow
);
168 return result
.Pass();
171 bool PickleAppListItem(Pickle
* pickle
, AppListItem
* item
) {
172 if (!pickle
->WriteString(item
->id()))
174 if (!pickle
->WriteString(item
->title()))
176 if (!pickle
->WriteString(item
->full_name()))
178 if (!pickle
->WriteBool(item
->has_shadow()))
180 if (!PickleImage(pickle
, item
->icon()))
185 void CopyOverItem(AppListItem
* src_item
, AppListItem
* dest_item
) {
186 dest_item
->SetTitleAndFullName(src_item
->title(), src_item
->full_name());
187 dest_item
->SetIcon(src_item
->icon(), src_item
->has_shadow());
192 // The version of the pickle format defined here. This needs to be incremented
193 // whenever this format is changed so new clients can invalidate old versions.
194 const int FastShowPickler::kVersion
= 3;
196 scoped_ptr
<Pickle
> FastShowPickler::PickleAppListModelForFastShow(
197 AppListModel
* model
) {
198 scoped_ptr
<Pickle
> result(new Pickle
);
199 if (!result
->WriteInt(kVersion
))
200 return scoped_ptr
<Pickle
>();
201 if (!result
->WriteInt((int) model
->item_list()->item_count()))
202 return scoped_ptr
<Pickle
>();
203 for (size_t i
= 0; i
< model
->item_list()->item_count(); ++i
) {
204 if (!PickleAppListItem(result
.get(), model
->item_list()->item_at(i
)))
205 return scoped_ptr
<Pickle
>();
207 return result
.Pass();
210 void FastShowPickler::CopyOver(AppListModel
* src
, AppListModel
* dest
) {
211 dest
->item_list()->DeleteItemsByType(NULL
/* all items */);
212 for (size_t i
= 0; i
< src
->item_list()->item_count(); i
++) {
213 AppListItem
* src_item
= src
->item_list()->item_at(i
);
214 AppListItem
* dest_item
= new AppListItem(src_item
->id());
215 CopyOverItem(src_item
, dest_item
);
216 dest
->item_list()->AddItem(dest_item
);
220 scoped_ptr
<AppListModel
>
221 FastShowPickler::UnpickleAppListModelForFastShow(Pickle
* pickle
) {
222 PickleIterator
it(*pickle
);
223 int read_version
= 0;
224 if (!it
.ReadInt(&read_version
))
225 return scoped_ptr
<AppListModel
>();
226 if (read_version
!= kVersion
)
227 return scoped_ptr
<AppListModel
>();
229 if (!it
.ReadInt(&app_count
))
230 return scoped_ptr
<AppListModel
>();
232 scoped_ptr
<AppListModel
> model(new AppListModel
);
233 for (int i
= 0; i
< app_count
; ++i
) {
234 scoped_ptr
<AppListItem
> item(UnpickleAppListItem(&it
).Pass());
236 return scoped_ptr
<AppListModel
>();
237 model
->item_list()->AddItem(item
.release());