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