Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2006-2008 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 "webkit/glue/webcursor.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/pickle.h"
      9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
     10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
     11 
     12 using WebKit::WebCursorInfo;
     13 using WebKit::WebImage;
     14 
     15 static const int kMaxCursorDimension = 1024;
     16 
     17 WebCursor::WebCursor()
     18     : type_(WebCursorInfo::TypePointer) {
     19   InitPlatformData();
     20 }
     21 
     22 WebCursor::WebCursor(const WebCursorInfo& cursor_info)
     23     : type_(WebCursorInfo::TypePointer) {
     24   InitPlatformData();
     25   InitFromCursorInfo(cursor_info);
     26 }
     27 
     28 WebCursor::~WebCursor() {
     29   Clear();
     30 }
     31 
     32 WebCursor::WebCursor(const WebCursor& other) {
     33   InitPlatformData();
     34   Copy(other);
     35 }
     36 
     37 const WebCursor& WebCursor::operator=(const WebCursor& other) {
     38   if (this == &other)
     39     return *this;
     40 
     41   Clear();
     42   Copy(other);
     43   return *this;
     44 }
     45 
     46 void WebCursor::InitFromCursorInfo(const WebCursorInfo& cursor_info) {
     47   Clear();
     48 
     49 #if defined(OS_WIN)
     50   if (cursor_info.externalHandle) {
     51     InitFromExternalCursor(cursor_info.externalHandle);
     52     return;
     53   }
     54 #endif
     55 
     56   type_ = cursor_info.type;
     57   hotspot_ = cursor_info.hotSpot;
     58   if (IsCustom())
     59     SetCustomData(cursor_info.customImage);
     60   ClampHotspot();
     61 }
     62 
     63 void WebCursor::GetCursorInfo(WebCursorInfo* cursor_info) const {
     64   cursor_info->type = static_cast<WebCursorInfo::Type>(type_);
     65   cursor_info->hotSpot = hotspot_;
     66   ImageFromCustomData(&cursor_info->customImage);
     67 
     68 #if defined(OS_WIN)
     69   cursor_info->externalHandle = external_cursor_;
     70 #endif
     71 }
     72 
     73 bool WebCursor::Deserialize(const Pickle* pickle, void** iter) {
     74   int type, hotspot_x, hotspot_y, size_x, size_y, data_len;
     75 
     76   const char* data;
     77 
     78   // Leave |this| unmodified unless we are going to return success.
     79   if (!pickle->ReadInt(iter, &type) ||
     80       !pickle->ReadInt(iter, &hotspot_x) ||
     81       !pickle->ReadInt(iter, &hotspot_y) ||
     82       !pickle->ReadLength(iter, &size_x) ||
     83       !pickle->ReadLength(iter, &size_y) ||
     84       !pickle->ReadData(iter, &data, &data_len))
     85     return false;
     86 
     87   // Ensure the size is sane, and there is enough data.
     88   if (size_x > kMaxCursorDimension ||
     89       size_y > kMaxCursorDimension)
     90     return false;
     91 
     92   type_ = type;
     93 
     94   if (type == WebCursorInfo::TypeCustom) {
     95     if (size_x > 0 && size_y > 0) {
     96       // The * 4 is because the expected format is an array of RGBA pixel
     97       // values.
     98       if (size_x * size_y * 4 > data_len)
     99         return false;
    100 
    101       hotspot_.set_x(hotspot_x);
    102       hotspot_.set_y(hotspot_y);
    103       custom_size_.set_width(size_x);
    104       custom_size_.set_height(size_y);
    105       ClampHotspot();
    106 
    107       custom_data_.clear();
    108       if (data_len > 0) {
    109         custom_data_.resize(data_len);
    110         memcpy(&custom_data_[0], data, data_len);
    111       }
    112     }
    113   }
    114   return DeserializePlatformData(pickle, iter);
    115 }
    116 
    117 bool WebCursor::Serialize(Pickle* pickle) const {
    118   if (!pickle->WriteInt(type_) ||
    119       !pickle->WriteInt(hotspot_.x()) ||
    120       !pickle->WriteInt(hotspot_.y()) ||
    121       !pickle->WriteInt(custom_size_.width()) ||
    122       !pickle->WriteInt(custom_size_.height()))
    123     return false;
    124 
    125   const char* data = NULL;
    126   if (!custom_data_.empty())
    127     data = &custom_data_[0];
    128   if (!pickle->WriteData(data, custom_data_.size()))
    129     return false;
    130 
    131   return SerializePlatformData(pickle);
    132 }
    133 
    134 bool WebCursor::IsCustom() const {
    135   return type_ == WebCursorInfo::TypeCustom;
    136 }
    137 
    138 bool WebCursor::IsEqual(const WebCursor& other) const {
    139   if (type_ != other.type_)
    140     return false;
    141 
    142   if (!IsPlatformDataEqual(other))
    143     return false;
    144 
    145   return hotspot_ == other.hotspot_ &&
    146          custom_size_ == other.custom_size_ &&
    147          custom_data_ == other.custom_data_;
    148 }
    149 
    150 void WebCursor::Clear() {
    151   type_ = WebCursorInfo::TypePointer;
    152   hotspot_.set_x(0);
    153   hotspot_.set_y(0);
    154   custom_size_.set_width(0);
    155   custom_size_.set_height(0);
    156   custom_data_.clear();
    157   CleanupPlatformData();
    158 }
    159 
    160 void WebCursor::Copy(const WebCursor& other) {
    161   type_ = other.type_;
    162   hotspot_ = other.hotspot_;
    163   custom_size_ = other.custom_size_;
    164   custom_data_ = other.custom_data_;
    165   CopyPlatformData(other);
    166 }
    167 
    168 #if WEBKIT_USING_SKIA
    169 // The WEBKIT_USING_CG implementation is in webcursor_mac.mm.
    170 void WebCursor::SetCustomData(const WebImage& image) {
    171   if (image.isNull())
    172     return;
    173 
    174   // Fill custom_data_ directly with the NativeImage pixels.
    175   const SkBitmap& bitmap = image.getSkBitmap();
    176   SkAutoLockPixels bitmap_lock(bitmap);
    177   custom_data_.resize(bitmap.getSize());
    178   if (!custom_data_.empty())
    179     memcpy(&custom_data_[0], bitmap.getPixels(), bitmap.getSize());
    180   custom_size_.set_width(bitmap.width());
    181   custom_size_.set_height(bitmap.height());
    182 }
    183 
    184 void WebCursor::ImageFromCustomData(WebImage* image) const {
    185   if (custom_data_.empty())
    186     return;
    187 
    188   SkBitmap bitmap;
    189   bitmap.setConfig(SkBitmap::kARGB_8888_Config,
    190                    custom_size_.width(),
    191                    custom_size_.height());
    192   if (!bitmap.allocPixels())
    193     return;
    194   memcpy(bitmap.getPixels(), &custom_data_[0], custom_data_.size());
    195 
    196   image->assign(bitmap);
    197 }
    198 #endif
    199 
    200 void WebCursor::ClampHotspot() {
    201   if (!IsCustom())
    202     return;
    203 
    204   // Clamp the hotspot to the custom image's dimensions.
    205   hotspot_.set_x(std::max(0,
    206                           std::min(custom_size_.width() - 1, hotspot_.x())));
    207   hotspot_.set_y(std::max(0,
    208                           std::min(custom_size_.height() - 1, hotspot_.y())));
    209 }
    210