fast_show_pickler.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
11namespace {
12
13using app_list::AppListItem;
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<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
171bool 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
185void 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.
195const int FastShowPickler::kVersion = 3;
196
197scoped_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
211void 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
221scoped_ptr<AppListModel>
222FastShowPickler::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}
244