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