Home | History | Annotate | Download | only in app_list
      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.h"
      9 #include "ui/gfx/image/image_skia_rep.h"
     10 
     11 namespace {
     12 
     13 using app_list::AppListItem;
     14 using 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.
     19 enum ImageFormat {
     20   NONE,
     21   A8,
     22   INDEX_8,
     23   RGB_565,
     24   ARGB_4444,
     25   ARGB_8888,
     26 };
     27 
     28 bool FormatToColorType(ImageFormat format, SkColorType* out) {
     29   switch (format) {
     30     case NONE:
     31       *out = kUnknown_SkColorType;
     32       break;
     33     case A8:
     34       *out = kAlpha_8_SkColorType;
     35       break;
     36     case INDEX_8:
     37       *out = kIndex_8_SkColorType;
     38       break;
     39     case RGB_565:
     40       *out = kRGB_565_SkColorType;
     41       break;
     42     case ARGB_4444:
     43       *out = kARGB_4444_SkColorType;
     44       break;
     45     case ARGB_8888:
     46       *out = kN32_SkColorType;
     47       break;
     48     default: return false;
     49   }
     50   return true;
     51 }
     52 
     53 bool ColorTypeToFormat(SkColorType colorType, ImageFormat* out) {
     54   switch (colorType) {
     55     case kUnknown_SkColorType:
     56       *out = NONE;
     57       break;
     58     case kAlpha_8_SkColorType:
     59       *out = A8;
     60       break;
     61     case kIndex_8_SkColorType:
     62       *out = INDEX_8;
     63       break;
     64     case kRGB_565_SkColorType:
     65       *out = RGB_565;
     66       break;
     67     case kARGB_4444_SkColorType:
     68       *out = ARGB_4444;
     69       break;
     70     case kN32_SkColorType:
     71       *out = ARGB_8888;
     72       break;
     73     default: return false;
     74   }
     75   return true;
     76 }
     77 
     78 bool 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 (!ColorTypeToFormat(it->sk_bitmap().colorType(), &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 
     99 bool 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     SkColorType color_type = kUnknown_SkColorType;
    123     if (!FormatToColorType(format, &color_type))
    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     if (!bitmap.tryAllocPixels(SkImageInfo::Make(
    136         width, height, color_type, kPremul_SkAlphaType)))
    137       return false;
    138 
    139     memcpy(bitmap.getPixels(), pixels, bitmap.getSize());
    140     result.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
    141   }
    142 
    143   *out = result;
    144   return true;
    145 }
    146 
    147 }  // namespace
    148 
    149 scoped_ptr<AppListItem> FastShowPickler::UnpickleAppListItem(
    150     PickleIterator* it) {
    151   std::string id;
    152   if (!it->ReadString(&id))
    153     return scoped_ptr<AppListItem>();
    154   scoped_ptr<AppListItem> result(new AppListItem(id));
    155   std::string name;
    156   if (!it->ReadString(&name))
    157     return scoped_ptr<AppListItem>();
    158   std::string short_name;
    159   if (!it->ReadString(&short_name))
    160     return scoped_ptr<AppListItem>();
    161   result->SetNameAndShortName(name, short_name);
    162   bool has_shadow = false;
    163   if (!it->ReadBool(&has_shadow))
    164     return scoped_ptr<AppListItem>();
    165   gfx::ImageSkia icon;
    166   if (!UnpickleImage(it, &icon))
    167     return scoped_ptr<AppListItem>();
    168   result->SetIcon(icon, has_shadow);
    169   return result.Pass();
    170 }
    171 
    172 bool FastShowPickler::PickleAppListItem(Pickle* pickle, AppListItem* item) {
    173   if (!pickle->WriteString(item->id()))
    174     return false;
    175   if (!pickle->WriteString(item->name()))
    176     return false;
    177   if (!pickle->WriteString(item->short_name()))
    178     return false;
    179   if (!pickle->WriteBool(item->has_shadow()))
    180     return false;
    181   if (!PickleImage(pickle, item->icon()))
    182     return false;
    183   return true;
    184 }
    185 
    186 void FastShowPickler::CopyOverItem(AppListItem* src_item,
    187                                    AppListItem* dest_item) {
    188   dest_item->SetNameAndShortName(src_item->name(), src_item->short_name());
    189   dest_item->SetIcon(src_item->icon(), src_item->has_shadow());
    190   // Do not set folder_id, pass that to AppListModel::AddItemToFolder() instead.
    191 }
    192 
    193 // The version of the pickle format defined here. This needs to be incremented
    194 // whenever this format is changed so new clients can invalidate old versions.
    195 const int FastShowPickler::kVersion = 3;
    196 
    197 scoped_ptr<Pickle> FastShowPickler::PickleAppListModelForFastShow(
    198     AppListModel* model) {
    199   scoped_ptr<Pickle> result(new Pickle);
    200   if (!result->WriteInt(kVersion))
    201     return scoped_ptr<Pickle>();
    202   if (!result->WriteInt((int)model->top_level_item_list()->item_count()))
    203     return scoped_ptr<Pickle>();
    204   for (size_t i = 0; i < model->top_level_item_list()->item_count(); ++i) {
    205     if (!PickleAppListItem(result.get(),
    206                            model->top_level_item_list()->item_at(i))) {
    207       return scoped_ptr<Pickle>();
    208     }
    209   }
    210   return result.Pass();
    211 }
    212 
    213 void FastShowPickler::CopyOver(AppListModel* src, AppListModel* dest) {
    214   DCHECK_EQ(0u, dest->top_level_item_list()->item_count());
    215   for (size_t i = 0; i < src->top_level_item_list()->item_count(); i++) {
    216     AppListItem* src_item = src->top_level_item_list()->item_at(i);
    217     scoped_ptr<AppListItem> dest_item(new AppListItem(src_item->id()));
    218     CopyOverItem(src_item, dest_item.get());
    219     dest->AddItemToFolder(dest_item.Pass(), src_item->folder_id());
    220   }
    221 }
    222 
    223 scoped_ptr<AppListModel>
    224 FastShowPickler::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   if (!it.ReadInt(&app_count))
    233     return scoped_ptr<AppListModel>();
    234 
    235   scoped_ptr<AppListModel> model(new AppListModel);
    236   for (int i = 0; i < app_count; ++i) {
    237     scoped_ptr<AppListItem> item(UnpickleAppListItem(&it).Pass());
    238     if (!item)
    239       return scoped_ptr<AppListModel>();
    240     std::string folder_id = item->folder_id();
    241     model->AddItemToFolder(item.Pass(), folder_id);
    242   }
    243 
    244   return model.Pass();
    245 }
    246