fast_show_pickler.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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  A1,
22  A8,
23  INDEX_8,
24  RGB_565,
25  ARGB_4444,
26  ARGB_8888,
27};
28
29bool FormatToConfig(ImageFormat format, SkBitmap::Config* out) {
30  switch (format) {
31    case NONE:
32      *out = SkBitmap::kNo_Config;
33      break;
34    case A1:
35      *out = SkBitmap::kA1_Config;
36      break;
37    case A8:
38      *out = SkBitmap::kA8_Config;
39      break;
40    case INDEX_8:
41      *out = SkBitmap::kIndex8_Config;
42      break;
43    case RGB_565:
44      *out = SkBitmap::kRGB_565_Config;
45      break;
46    case ARGB_4444:
47      *out = SkBitmap::kARGB_4444_Config;
48      break;
49    case ARGB_8888:
50      *out = SkBitmap::kARGB_8888_Config;
51      break;
52    default: return false;
53  }
54  return true;
55}
56
57bool ConfigToFormat(SkBitmap::Config config, ImageFormat* out) {
58  switch (config) {
59    case SkBitmap::kNo_Config:
60      *out = NONE;
61      break;
62    case SkBitmap::kA1_Config:
63      *out = A1;
64      break;
65    case SkBitmap::kA8_Config:
66      *out = A8;
67      break;
68    case SkBitmap::kIndex8_Config:
69      *out = INDEX_8;
70      break;
71    case SkBitmap::kRGB_565_Config:
72      *out = RGB_565;
73      break;
74    case SkBitmap::kARGB_4444_Config:
75      *out = ARGB_4444;
76      break;
77    case SkBitmap::kARGB_8888_Config:
78      *out = ARGB_8888;
79      break;
80    default: return false;
81  }
82  return true;
83}
84
85bool PickleImage(Pickle* pickle, const gfx::ImageSkia& image) {
86  std::vector<gfx::ImageSkiaRep> reps(image.image_reps());
87  pickle->WriteInt(static_cast<int>(reps.size()));
88  for (std::vector<gfx::ImageSkiaRep>::const_iterator it = reps.begin();
89       it != reps.end(); ++it) {
90    pickle->WriteFloat(it->scale());
91    pickle->WriteInt(it->pixel_width());
92    pickle->WriteInt(it->pixel_height());
93    ImageFormat format = NONE;
94    if (!ConfigToFormat(it->sk_bitmap().getConfig(), &format))
95      return false;
96    pickle->WriteInt(static_cast<int>(format));
97    int size = static_cast<int>(it->sk_bitmap().getSafeSize());
98    pickle->WriteInt(size);
99    SkBitmap bitmap = it->sk_bitmap();
100    SkAutoLockPixels lock(bitmap);
101    pickle->WriteBytes(bitmap.getPixels(), size);
102  }
103  return true;
104}
105
106bool UnpickleImage(PickleIterator* it, gfx::ImageSkia* out) {
107  int rep_count = 0;
108  if (!it->ReadInt(&rep_count))
109    return false;
110
111  gfx::ImageSkia result;
112  for (int i = 0; i < rep_count; ++i) {
113    float scale = 0.0f;
114    if (!it->ReadFloat(&scale))
115      return false;
116
117    int width = 0;
118    if (!it->ReadInt(&width))
119      return false;
120
121    int height = 0;
122    if (!it->ReadInt(&height))
123      return false;
124
125    int format_int = 0;
126    if (!it->ReadInt(&format_int))
127      return false;
128    ImageFormat format = static_cast<ImageFormat>(format_int);
129    SkBitmap::Config config = SkBitmap::kNo_Config;
130    if (!FormatToConfig(format, &config))
131      return false;
132
133    int size = 0;
134    if (!it->ReadInt(&size))
135      return false;
136
137    const char* pixels = NULL;
138    if (!it->ReadBytes(&pixels, size))
139      return false;
140
141    SkBitmap bitmap;
142    bitmap.setConfig(static_cast<SkBitmap::Config>(config), width, height);
143    if (!bitmap.allocPixels())
144      return false;
145    {
146      SkAutoLockPixels lock(bitmap);
147      memcpy(bitmap.getPixels(), pixels, bitmap.getSize());
148    }
149    result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
150  }
151
152  *out = result;
153  return true;
154}
155
156scoped_ptr<AppListItemModel> UnpickleAppListItemModel(PickleIterator* it) {
157  std::string id;
158  if (!it->ReadString(&id))
159    return scoped_ptr<AppListItemModel>();
160  scoped_ptr<AppListItemModel> result(new AppListItemModel(id));
161  std::string title;
162  if (!it->ReadString(&title))
163    return scoped_ptr<AppListItemModel>();
164  std::string full_name;
165  if (!it->ReadString(&full_name))
166    return scoped_ptr<AppListItemModel>();
167  result->SetTitleAndFullName(title, full_name);
168  bool has_shadow = false;
169  if (!it->ReadBool(&has_shadow))
170    return scoped_ptr<AppListItemModel>();
171  gfx::ImageSkia icon;
172  if (!UnpickleImage(it, &icon))
173    return scoped_ptr<AppListItemModel>();
174  result->SetIcon(icon, has_shadow);
175  return result.Pass();
176}
177
178bool PickleAppListItemModel(Pickle* pickle, AppListItemModel* item) {
179  if (!pickle->WriteString(item->id()))
180    return false;
181  if (!pickle->WriteString(item->title()))
182    return false;
183  if (!pickle->WriteString(item->full_name()))
184    return false;
185  if (!pickle->WriteBool(item->has_shadow()))
186    return false;
187  if (!PickleImage(pickle, item->icon()))
188    return false;
189  return true;
190}
191
192void CopyOverItem(AppListItemModel* src_item, AppListItemModel* dest_item) {
193  dest_item->SetTitleAndFullName(src_item->title(), src_item->full_name());
194  dest_item->SetIcon(src_item->icon(), src_item->has_shadow());
195}
196
197}  // namespace
198
199// The version of the pickle format defined here. This needs to be incremented
200// whenever this format is changed so new clients can invalidate old versions.
201const int FastShowPickler::kVersion = 1;
202
203scoped_ptr<Pickle> FastShowPickler::PickleAppListModelForFastShow(
204    AppListModel* model) {
205  scoped_ptr<Pickle> result(new Pickle);
206  if (!result->WriteInt(kVersion))
207    return scoped_ptr<Pickle>();
208  if (!result->WriteBool(model->signed_in()))
209    return scoped_ptr<Pickle>();
210  if (!result->WriteInt((int) model->item_list()->item_count()))
211    return scoped_ptr<Pickle>();
212  for (size_t i = 0; i < model->item_list()->item_count(); ++i) {
213    if (!PickleAppListItemModel(result.get(), model->item_list()->item_at(i)))
214      return scoped_ptr<Pickle>();
215  }
216  return result.Pass();
217}
218
219void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) {
220  dest->item_list()->DeleteItemsByType(NULL /* all items */);
221  dest->SetSignedIn(src->signed_in());
222  for (size_t i = 0; i < src->item_list()->item_count(); i++) {
223    AppListItemModel* src_item = src->item_list()->item_at(i);
224    AppListItemModel* dest_item = new AppListItemModel(src_item->id());
225    CopyOverItem(src_item, dest_item);
226    dest->item_list()->AddItem(dest_item);
227  }
228}
229
230scoped_ptr<AppListModel>
231FastShowPickler::UnpickleAppListModelForFastShow(Pickle* pickle) {
232  PickleIterator it(*pickle);
233  int read_version = 0;
234  if (!it.ReadInt(&read_version))
235    return scoped_ptr<AppListModel>();
236  if (read_version != kVersion)
237    return scoped_ptr<AppListModel>();
238  int app_count = 0;
239  bool signed_in = false;
240  if (!it.ReadBool(&signed_in))
241    return scoped_ptr<AppListModel>();
242  if (!it.ReadInt(&app_count))
243    return scoped_ptr<AppListModel>();
244
245  scoped_ptr<AppListModel> model(new AppListModel);
246  model->SetSignedIn(signed_in);
247  for (int i = 0; i < app_count; ++i) {
248    scoped_ptr<AppListItemModel> item(UnpickleAppListItemModel(&it).Pass());
249    if (!item)
250      return scoped_ptr<AppListModel>();
251    model->item_list()->AddItem(item.release());
252  }
253
254  return model.Pass();
255}
256