c121ded54787ee91a81a23ffa4f304c57474cb89
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / fast_show_pickler.cc
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.
4
5 #include "chrome/browser/ui/app_list/fast_show_pickler.h"
6
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"
10
11 namespace {
12
13 using app_list::AppListItem;
14 using app_list::AppListModel;
15
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.
19 enum ImageFormat {
20   NONE,
21   A8,
22   INDEX_8,
23   RGB_565,
24   ARGB_4444,
25   ARGB_8888,
26 };
27
28 bool FormatToConfig(ImageFormat format, SkBitmap::Config* out) {
29   switch (format) {
30     case NONE:
31       *out = SkBitmap::kNo_Config;
32       break;
33     case A8:
34       *out = SkBitmap::kA8_Config;
35       break;
36     case INDEX_8:
37       *out = SkBitmap::kIndex8_Config;
38       break;
39     case RGB_565:
40       *out = SkBitmap::kRGB_565_Config;
41       break;
42     case ARGB_4444:
43       *out = SkBitmap::kARGB_4444_Config;
44       break;
45     case ARGB_8888:
46       *out = SkBitmap::kARGB_8888_Config;
47       break;
48     default: return false;
49   }
50   return true;
51 }
52
53 bool ConfigToFormat(SkBitmap::Config config, ImageFormat* out) {
54   switch (config) {
55     case SkBitmap::kNo_Config:
56       *out = NONE;
57       break;
58     case SkBitmap::kA8_Config:
59       *out = A8;
60       break;
61     case SkBitmap::kIndex8_Config:
62       *out = INDEX_8;
63       break;
64     case SkBitmap::kRGB_565_Config:
65       *out = RGB_565;
66       break;
67     case SkBitmap::kARGB_4444_Config:
68       *out = ARGB_4444;
69       break;
70     case SkBitmap::kARGB_8888_Config:
71       *out = ARGB_8888;
72       break;
73     default: return false;
74   }
75   return true;
76 }
77
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))
88       return false;
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);
95   }
96   return true;
97 }
98
99 bool UnpickleImage(PickleIterator* it, gfx::ImageSkia* out) {
100   int rep_count = 0;
101   if (!it->ReadInt(&rep_count))
102     return false;
103
104   gfx::ImageSkia result;
105   for (int i = 0; i < rep_count; ++i) {
106     float scale = 0.0f;
107     if (!it->ReadFloat(&scale))
108       return false;
109
110     int width = 0;
111     if (!it->ReadInt(&width))
112       return false;
113
114     int height = 0;
115     if (!it->ReadInt(&height))
116       return false;
117
118     int format_int = 0;
119     if (!it->ReadInt(&format_int))
120       return false;
121     ImageFormat format = static_cast<ImageFormat>(format_int);
122     SkBitmap::Config config = SkBitmap::kNo_Config;
123     if (!FormatToConfig(format, &config))
124       return false;
125
126     int size = 0;
127     if (!it->ReadInt(&size))
128       return false;
129
130     const char* pixels = NULL;
131     if (!it->ReadBytes(&pixels, size))
132       return false;
133
134     SkBitmap bitmap;
135     bitmap.setConfig(static_cast<SkBitmap::Config>(config), width, height);
136     if (!bitmap.allocPixels())
137       return false;
138     {
139       SkAutoLockPixels lock(bitmap);
140       memcpy(bitmap.getPixels(), pixels, bitmap.getSize());
141     }
142     result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
143   }
144
145   *out = result;
146   return true;
147 }
148
149 scoped_ptr<AppListItem> UnpickleAppListItem(PickleIterator* it) {
150   std::string id;
151   if (!it->ReadString(&id))
152     return scoped_ptr<AppListItem>();
153   scoped_ptr<AppListItem> result(new AppListItem(id));
154   std::string title;
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>();
164   gfx::ImageSkia icon;
165   if (!UnpickleImage(it, &icon))
166     return scoped_ptr<AppListItem>();
167   result->SetIcon(icon, has_shadow);
168   return result.Pass();
169 }
170
171 bool PickleAppListItem(Pickle* pickle, AppListItem* item) {
172   if (!pickle->WriteString(item->id()))
173     return false;
174   if (!pickle->WriteString(item->title()))
175     return false;
176   if (!pickle->WriteString(item->full_name()))
177     return false;
178   if (!pickle->WriteBool(item->has_shadow()))
179     return false;
180   if (!PickleImage(pickle, item->icon()))
181     return false;
182   return true;
183 }
184
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.
189 }
190
191 }  // namespace
192
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;
196
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>();
207   }
208   return result.Pass();
209 }
210
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());
218   }
219 }
220
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>();
229   int app_count = 0;
230   if (!it.ReadInt(&app_count))
231     return scoped_ptr<AppListModel>();
232
233   scoped_ptr<AppListModel> model(new AppListModel);
234   for (int i = 0; i < app_count; ++i) {
235     scoped_ptr<AppListItem> item(UnpickleAppListItem(&it).Pass());
236     if (!item)
237       return scoped_ptr<AppListModel>();
238     std::string folder_id = item->folder_id();
239     model->AddItemToFolder(item.Pass(), folder_id);
240   }
241
242   return model.Pass();
243 }