fast_show_pickler.cc revision f2477e01787aa58f445919b809d89e252beef54f
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_model.h"
9#include "ui/gfx/image/image_skia_rep.h"
10
11namespace {
12
13using app_list::AppListItemModel;
14using 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.
19enum ImageFormat {
20  NONE,
21  A8,
22  INDEX_8,
23  RGB_565,
24  ARGB_4444,
25  ARGB_8888,
26};
27
28bool 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
53bool 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
78bool 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
99bool 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
149scoped_ptr<AppListItemModel> UnpickleAppListItemModel(PickleIterator* it) {
150  std::string id;
151  if (!it->ReadString(&id))
152    return scoped_ptr<AppListItemModel>();
153  scoped_ptr<AppListItemModel> result(new AppListItemModel(id));
154  std::string title;
155  if (!it->ReadString(&title))
156    return scoped_ptr<AppListItemModel>();
157  std::string full_name;
158  if (!it->ReadString(&full_name))
159    return scoped_ptr<AppListItemModel>();
160  result->SetTitleAndFullName(title, full_name);
161  bool has_shadow = false;
162  if (!it->ReadBool(&has_shadow))
163    return scoped_ptr<AppListItemModel>();
164  gfx::ImageSkia icon;
165  if (!UnpickleImage(it, &icon))
166    return scoped_ptr<AppListItemModel>();
167  result->SetIcon(icon, has_shadow);
168  return result.Pass();
169}
170
171bool PickleAppListItemModel(Pickle* pickle, AppListItemModel* 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
185void CopyOverItem(AppListItemModel* src_item, AppListItemModel* 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}
189
190}  // namespace
191
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.
194const int FastShowPickler::kVersion = 2;
195
196scoped_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->WriteBool(model->signed_in()))
202    return scoped_ptr<Pickle>();
203  if (!result->WriteInt((int) model->item_list()->item_count()))
204    return scoped_ptr<Pickle>();
205  for (size_t i = 0; i < model->item_list()->item_count(); ++i) {
206    if (!PickleAppListItemModel(result.get(), model->item_list()->item_at(i)))
207      return scoped_ptr<Pickle>();
208  }
209  return result.Pass();
210}
211
212void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) {
213  dest->item_list()->DeleteItemsByType(NULL /* all items */);
214  dest->SetSignedIn(src->signed_in());
215  for (size_t i = 0; i < src->item_list()->item_count(); i++) {
216    AppListItemModel* src_item = src->item_list()->item_at(i);
217    AppListItemModel* dest_item = new AppListItemModel(src_item->id());
218    CopyOverItem(src_item, dest_item);
219    dest->item_list()->AddItem(dest_item);
220  }
221}
222
223scoped_ptr<AppListModel>
224FastShowPickler::UnpickleAppListModelForFastShow(Pickle* pickle) {
225  PickleIterator it(*pickle);
226  int read_version = 0;
227  if (!it.ReadInt(&read_version))
228    return scoped_ptr<AppListModel>();
229  if (read_version != kVersion)
230    return scoped_ptr<AppListModel>();
231  int app_count = 0;
232  bool signed_in = false;
233  if (!it.ReadBool(&signed_in))
234    return scoped_ptr<AppListModel>();
235  if (!it.ReadInt(&app_count))
236    return scoped_ptr<AppListModel>();
237
238  scoped_ptr<AppListModel> model(new AppListModel);
239  model->SetSignedIn(signed_in);
240  for (int i = 0; i < app_count; ++i) {
241    scoped_ptr<AppListItemModel> item(UnpickleAppListItemModel(&it).Pass());
242    if (!item)
243      return scoped_ptr<AppListModel>();
244    model->item_list()->AddItem(item.release());
245  }
246
247  return model.Pass();
248}
249