fast_show_pickler.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 12namespace { 13 14using app_list::AppListItemModel; 15using 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. 20enum ImageFormat { 21 NONE, 22 A1, 23 A8, 24 INDEX_8, 25 RGB_565, 26 ARGB_4444, 27 ARGB_8888, 28}; 29 30bool 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 58bool 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 86bool 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>(ui::GetSupportedScaleFactor(it->scale()))); 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 107bool 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 float scale = ui::GetImageScale(static_cast<ui::ScaleFactor>(scale_factor)); 151 result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); 152 } 153 154 *out = result; 155 return true; 156} 157 158scoped_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 181bool 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 195void 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. 205const int FastShowPickler::kVersion = 1; 206 207scoped_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 223void 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 234scoped_ptr<AppListModel> 235FastShowPickler::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} 260