| 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 <stddef.h> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "third_party/skia/include/core/SkBitmap.h" | |
| 11 #include "ui/app_list/app_list_item.h" | |
| 12 #include "ui/gfx/image/image_skia_rep.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 using app_list::AppListItem; | |
| 17 using app_list::AppListModel; | |
| 18 | |
| 19 // These have the same meaning as SkBitmap::Config. Reproduced here to insure | |
| 20 // against their value changing in Skia. If the order of these changes kVersion | |
| 21 // should be incremented. | |
| 22 enum ImageFormat { | |
| 23 NONE, | |
| 24 A8, | |
| 25 INDEX_8, | |
| 26 RGB_565, | |
| 27 ARGB_4444, | |
| 28 ARGB_8888, | |
| 29 }; | |
| 30 | |
| 31 bool FormatToColorType(ImageFormat format, SkColorType* out) { | |
| 32 switch (format) { | |
| 33 case NONE: | |
| 34 *out = kUnknown_SkColorType; | |
| 35 break; | |
| 36 case A8: | |
| 37 *out = kAlpha_8_SkColorType; | |
| 38 break; | |
| 39 case INDEX_8: | |
| 40 *out = kIndex_8_SkColorType; | |
| 41 break; | |
| 42 case RGB_565: | |
| 43 *out = kRGB_565_SkColorType; | |
| 44 break; | |
| 45 case ARGB_4444: | |
| 46 *out = kARGB_4444_SkColorType; | |
| 47 break; | |
| 48 case ARGB_8888: | |
| 49 *out = kN32_SkColorType; | |
| 50 break; | |
| 51 default: return false; | |
| 52 } | |
| 53 return true; | |
| 54 } | |
| 55 | |
| 56 bool ColorTypeToFormat(SkColorType colorType, ImageFormat* out) { | |
| 57 switch (colorType) { | |
| 58 case kUnknown_SkColorType: | |
| 59 *out = NONE; | |
| 60 break; | |
| 61 case kAlpha_8_SkColorType: | |
| 62 *out = A8; | |
| 63 break; | |
| 64 case kIndex_8_SkColorType: | |
| 65 *out = INDEX_8; | |
| 66 break; | |
| 67 case kRGB_565_SkColorType: | |
| 68 *out = RGB_565; | |
| 69 break; | |
| 70 case kARGB_4444_SkColorType: | |
| 71 *out = ARGB_4444; | |
| 72 break; | |
| 73 case kN32_SkColorType: | |
| 74 *out = ARGB_8888; | |
| 75 break; | |
| 76 default: return false; | |
| 77 } | |
| 78 return true; | |
| 79 } | |
| 80 | |
| 81 bool PickleImage(base::Pickle* pickle, const gfx::ImageSkia& image) { | |
| 82 std::vector<gfx::ImageSkiaRep> reps(image.image_reps()); | |
| 83 pickle->WriteInt(static_cast<int>(reps.size())); | |
| 84 for (std::vector<gfx::ImageSkiaRep>::const_iterator it = reps.begin(); | |
| 85 it != reps.end(); ++it) { | |
| 86 pickle->WriteFloat(it->scale()); | |
| 87 pickle->WriteInt(it->pixel_width()); | |
| 88 pickle->WriteInt(it->pixel_height()); | |
| 89 ImageFormat format = NONE; | |
| 90 if (!ColorTypeToFormat(it->sk_bitmap().colorType(), &format)) | |
| 91 return false; | |
| 92 pickle->WriteInt(static_cast<int>(format)); | |
| 93 int size = static_cast<int>(it->sk_bitmap().getSafeSize()); | |
| 94 pickle->WriteInt(size); | |
| 95 SkBitmap bitmap = it->sk_bitmap(); | |
| 96 SkAutoLockPixels lock(bitmap); | |
| 97 pickle->WriteBytes(bitmap.getPixels(), size); | |
| 98 } | |
| 99 return true; | |
| 100 } | |
| 101 | |
| 102 bool UnpickleImage(base::PickleIterator* it, gfx::ImageSkia* out) { | |
| 103 int rep_count = 0; | |
| 104 if (!it->ReadInt(&rep_count)) | |
| 105 return false; | |
| 106 | |
| 107 gfx::ImageSkia result; | |
| 108 for (int i = 0; i < rep_count; ++i) { | |
| 109 float scale = 0.0f; | |
| 110 if (!it->ReadFloat(&scale)) | |
| 111 return false; | |
| 112 | |
| 113 int width = 0; | |
| 114 if (!it->ReadInt(&width)) | |
| 115 return false; | |
| 116 | |
| 117 int height = 0; | |
| 118 if (!it->ReadInt(&height)) | |
| 119 return false; | |
| 120 | |
| 121 int format_int = 0; | |
| 122 if (!it->ReadInt(&format_int)) | |
| 123 return false; | |
| 124 ImageFormat format = static_cast<ImageFormat>(format_int); | |
| 125 SkColorType color_type = kUnknown_SkColorType; | |
| 126 if (!FormatToColorType(format, &color_type)) | |
| 127 return false; | |
| 128 | |
| 129 int size = 0; | |
| 130 if (!it->ReadInt(&size)) | |
| 131 return false; | |
| 132 | |
| 133 const char* pixels = NULL; | |
| 134 if (!it->ReadBytes(&pixels, size)) | |
| 135 return false; | |
| 136 | |
| 137 SkBitmap bitmap; | |
| 138 if (!bitmap.tryAllocPixels(SkImageInfo::Make( | |
| 139 width, height, color_type, kPremul_SkAlphaType))) | |
| 140 return false; | |
| 141 | |
| 142 memcpy(bitmap.getPixels(), pixels, bitmap.getSize()); | |
| 143 result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale)); | |
| 144 } | |
| 145 | |
| 146 *out = result; | |
| 147 return true; | |
| 148 } | |
| 149 | |
| 150 } // namespace | |
| 151 | |
| 152 std::unique_ptr<AppListItem> FastShowPickler::UnpickleAppListItem( | |
| 153 base::PickleIterator* it) { | |
| 154 std::string id; | |
| 155 if (!it->ReadString(&id)) | |
| 156 return std::unique_ptr<AppListItem>(); | |
| 157 std::unique_ptr<AppListItem> result(new AppListItem(id)); | |
| 158 std::string name; | |
| 159 if (!it->ReadString(&name)) | |
| 160 return std::unique_ptr<AppListItem>(); | |
| 161 std::string short_name; | |
| 162 if (!it->ReadString(&short_name)) | |
| 163 return std::unique_ptr<AppListItem>(); | |
| 164 result->SetNameAndShortName(name, short_name); | |
| 165 gfx::ImageSkia icon; | |
| 166 if (!UnpickleImage(it, &icon)) | |
| 167 return std::unique_ptr<AppListItem>(); | |
| 168 result->SetIcon(icon); | |
| 169 return result; | |
| 170 } | |
| 171 | |
| 172 bool FastShowPickler::PickleAppListItem(base::Pickle* pickle, | |
| 173 AppListItem* item) { | |
| 174 if (!pickle->WriteString(item->id())) | |
| 175 return false; | |
| 176 if (!pickle->WriteString(item->name())) | |
| 177 return false; | |
| 178 if (!pickle->WriteString(item->short_name())) | |
| 179 return false; | |
| 180 if (!PickleImage(pickle, item->icon())) | |
| 181 return false; | |
| 182 return true; | |
| 183 } | |
| 184 | |
| 185 void FastShowPickler::CopyOverItem(AppListItem* src_item, | |
| 186 AppListItem* dest_item) { | |
| 187 dest_item->SetNameAndShortName(src_item->name(), src_item->short_name()); | |
| 188 dest_item->SetIcon(src_item->icon()); | |
| 189 // Do not set folder_id, pass that to AppListModel::AddItemToFolder() instead. | |
| 190 } | |
| 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. | |
| 194 const int FastShowPickler::kVersion = 4; | |
| 195 | |
| 196 std::unique_ptr<base::Pickle> FastShowPickler::PickleAppListModelForFastShow( | |
| 197 AppListModel* model) { | |
| 198 std::unique_ptr<base::Pickle> result(new base::Pickle); | |
| 199 if (!result->WriteInt(kVersion)) | |
| 200 return std::unique_ptr<base::Pickle>(); | |
| 201 if (!result->WriteInt((int)model->top_level_item_list()->item_count())) | |
| 202 return std::unique_ptr<base::Pickle>(); | |
| 203 for (size_t i = 0; i < model->top_level_item_list()->item_count(); ++i) { | |
| 204 if (!PickleAppListItem(result.get(), | |
| 205 model->top_level_item_list()->item_at(i))) { | |
| 206 return std::unique_ptr<base::Pickle>(); | |
| 207 } | |
| 208 } | |
| 209 return result; | |
| 210 } | |
| 211 | |
| 212 void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) { | |
| 213 DCHECK_EQ(0u, dest->top_level_item_list()->item_count()); | |
| 214 for (size_t i = 0; i < src->top_level_item_list()->item_count(); i++) { | |
| 215 AppListItem* src_item = src->top_level_item_list()->item_at(i); | |
| 216 std::unique_ptr<AppListItem> dest_item(new AppListItem(src_item->id())); | |
| 217 CopyOverItem(src_item, dest_item.get()); | |
| 218 dest->AddItemToFolder(std::move(dest_item), src_item->folder_id()); | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 std::unique_ptr<AppListModel> FastShowPickler::UnpickleAppListModelForFastShow( | |
| 223 base::Pickle* pickle) { | |
| 224 base::PickleIterator it(*pickle); | |
| 225 int read_version = 0; | |
| 226 if (!it.ReadInt(&read_version)) | |
| 227 return std::unique_ptr<AppListModel>(); | |
| 228 if (read_version != kVersion) | |
| 229 return std::unique_ptr<AppListModel>(); | |
| 230 int app_count = 0; | |
| 231 if (!it.ReadInt(&app_count)) | |
| 232 return std::unique_ptr<AppListModel>(); | |
| 233 | |
| 234 std::unique_ptr<AppListModel> model(new AppListModel); | |
| 235 for (int i = 0; i < app_count; ++i) { | |
| 236 std::unique_ptr<AppListItem> item(UnpickleAppListItem(&it)); | |
| 237 if (!item) | |
| 238 return std::unique_ptr<AppListModel>(); | |
| 239 std::string folder_id = item->folder_id(); | |
| 240 model->AddItemToFolder(std::move(item), folder_id); | |
| 241 } | |
| 242 | |
| 243 return model; | |
| 244 } | |
| OLD | NEW |