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 |