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());
188 // Do not set folder_id, pass that to AppListModel::AddItemToFolder() instead.
193 // The version of the pickle format defined here. This needs to be incremented
194 // whenever this format is changed so new clients can invalidate old versions.
195 const int FastShowPickler::kVersion = 3;
197 scoped_ptr<Pickle> FastShowPickler::PickleAppListModelForFastShow(
198 AppListModel* model) {
199 scoped_ptr<Pickle> result(new Pickle);
200 if (!result->WriteInt(kVersion))
201 return scoped_ptr<Pickle>();
202 if (!result->WriteInt((int) model->item_list()->item_count()))
203 return scoped_ptr<Pickle>();
204 for (size_t i = 0; i < model->item_list()->item_count(); ++i) {
205 if (!PickleAppListItem(result.get(), model->item_list()->item_at(i)))
206 return scoped_ptr<Pickle>();
208 return result.Pass();
211 void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) {
212 DCHECK_EQ(0u, dest->item_list()->item_count());
213 for (size_t i = 0; i < src->item_list()->item_count(); i++) {
214 AppListItem* src_item = src->item_list()->item_at(i);
215 scoped_ptr<AppListItem> dest_item(new AppListItem(src_item->id()));
216 CopyOverItem(src_item, dest_item.get());
217 dest->AddItemToFolder(dest_item.Pass(), src_item->folder_id());
221 scoped_ptr<AppListModel>
222 FastShowPickler::UnpickleAppListModelForFastShow(Pickle* pickle) {
223 PickleIterator it(*pickle);
224 int read_version = 0;
225 if (!it.ReadInt(&read_version))
226 return scoped_ptr<AppListModel>();
227 if (read_version != kVersion)
228 return scoped_ptr<AppListModel>();
230 if (!it.ReadInt(&app_count))
231 return scoped_ptr<AppListModel>();
233 scoped_ptr<AppListModel> model(new AppListModel);
234 for (int i = 0; i < app_count; ++i) {
235 scoped_ptr<AppListItem> item(UnpickleAppListItem(&it).Pass());
237 return scoped_ptr<AppListModel>();
238 std::string folder_id = item->folder_id();
239 model->AddItemToFolder(item.Pass(), folder_id);