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