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 12using WebKit::WebCursorInfo; 13using WebKit::WebImage; 14 15static const int kMaxCursorDimension = 1024; 16 17WebCursor::WebCursor() 18 : type_(WebCursorInfo::TypePointer) { 19 InitPlatformData(); 20} 21 22WebCursor::WebCursor(const WebCursorInfo& cursor_info) 23 : type_(WebCursorInfo::TypePointer) { 24 InitPlatformData(); 25 InitFromCursorInfo(cursor_info); 26} 27 28WebCursor::~WebCursor() { 29 Clear(); 30} 31 32WebCursor::WebCursor(const WebCursor& other) { 33 InitPlatformData(); 34 Copy(other); 35} 36 37const WebCursor& WebCursor::operator=(const WebCursor& other) { 38 if (this == &other) 39 return *this; 40 41 Clear(); 42 Copy(other); 43 return *this; 44} 45 46void 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 63void 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 73bool 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 117bool 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 134bool WebCursor::IsCustom() const { 135 return type_ == WebCursorInfo::TypeCustom; 136} 137 138bool 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 150void 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 160void 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. 170void 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 184void 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 200void 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