| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/Platform/chromium/public/WebImage.h" | |
| 10 | |
| 11 using WebKit::WebCursorInfo; | |
| 12 | |
| 13 static const int kMaxCursorDimension = 1024; | |
| 14 | |
| 15 WebCursor::WebCursor() | |
| 16 : type_(WebCursorInfo::TypePointer), | |
| 17 custom_scale_(1) { | |
| 18 #if defined(OS_WIN) | |
| 19 external_cursor_ = NULL; | |
| 20 #endif | |
| 21 InitPlatformData(); | |
| 22 } | |
| 23 | |
| 24 WebCursor::WebCursor(const CursorInfo& cursor_info) | |
| 25 : type_(WebCursorInfo::TypePointer) { | |
| 26 #if defined(OS_WIN) | |
| 27 external_cursor_ = NULL; | |
| 28 #endif | |
| 29 InitPlatformData(); | |
| 30 InitFromCursorInfo(cursor_info); | |
| 31 } | |
| 32 | |
| 33 WebCursor::~WebCursor() { | |
| 34 Clear(); | |
| 35 } | |
| 36 | |
| 37 WebCursor::WebCursor(const WebCursor& other) { | |
| 38 InitPlatformData(); | |
| 39 Copy(other); | |
| 40 } | |
| 41 | |
| 42 const WebCursor& WebCursor::operator=(const WebCursor& other) { | |
| 43 if (this == &other) | |
| 44 return *this; | |
| 45 | |
| 46 Clear(); | |
| 47 Copy(other); | |
| 48 return *this; | |
| 49 } | |
| 50 | |
| 51 void WebCursor::InitFromCursorInfo(const CursorInfo& cursor_info) { | |
| 52 Clear(); | |
| 53 | |
| 54 #if defined(OS_WIN) | |
| 55 if (cursor_info.external_handle) { | |
| 56 InitFromExternalCursor(cursor_info.external_handle); | |
| 57 return; | |
| 58 } | |
| 59 #endif | |
| 60 | |
| 61 type_ = cursor_info.type; | |
| 62 hotspot_ = cursor_info.hotspot; | |
| 63 if (IsCustom()) | |
| 64 SetCustomData(cursor_info.custom_image); | |
| 65 custom_scale_ = cursor_info.image_scale_factor; | |
| 66 CHECK(custom_scale_ > 0); | |
| 67 ClampHotspot(); | |
| 68 } | |
| 69 | |
| 70 void WebCursor::GetCursorInfo(CursorInfo* cursor_info) const { | |
| 71 cursor_info->type = static_cast<WebCursorInfo::Type>(type_); | |
| 72 cursor_info->hotspot = hotspot_; | |
| 73 ImageFromCustomData(&cursor_info->custom_image); | |
| 74 cursor_info->image_scale_factor = custom_scale_; | |
| 75 | |
| 76 #if defined(OS_WIN) | |
| 77 cursor_info->external_handle = external_cursor_; | |
| 78 #endif | |
| 79 } | |
| 80 | |
| 81 bool WebCursor::Deserialize(PickleIterator* iter) { | |
| 82 int type, hotspot_x, hotspot_y, size_x, size_y, data_len; | |
| 83 float scale; | |
| 84 const char* data; | |
| 85 | |
| 86 // Leave |this| unmodified unless we are going to return success. | |
| 87 if (!iter->ReadInt(&type) || | |
| 88 !iter->ReadInt(&hotspot_x) || | |
| 89 !iter->ReadInt(&hotspot_y) || | |
| 90 !iter->ReadLength(&size_x) || | |
| 91 !iter->ReadLength(&size_y) || | |
| 92 !iter->ReadFloat(&scale) || | |
| 93 !iter->ReadData(&data, &data_len)) | |
| 94 return false; | |
| 95 | |
| 96 // Ensure the size is sane, and there is enough data. | |
| 97 if (size_x > kMaxCursorDimension || | |
| 98 size_y > kMaxCursorDimension) | |
| 99 return false; | |
| 100 | |
| 101 // Ensure scale isn't ridiculous, and the scaled image size is still sane. | |
| 102 if (scale < 0.01 || scale > 100 || | |
| 103 size_x / scale > kMaxCursorDimension || | |
| 104 size_y / scale > kMaxCursorDimension) | |
| 105 return false; | |
| 106 | |
| 107 type_ = type; | |
| 108 | |
| 109 if (type == WebCursorInfo::TypeCustom) { | |
| 110 if (size_x > 0 && size_y > 0) { | |
| 111 // The * 4 is because the expected format is an array of RGBA pixel | |
| 112 // values. | |
| 113 if (size_x * size_y * 4 > data_len) | |
| 114 return false; | |
| 115 | |
| 116 hotspot_.set_x(hotspot_x); | |
| 117 hotspot_.set_y(hotspot_y); | |
| 118 custom_size_.set_width(size_x); | |
| 119 custom_size_.set_height(size_y); | |
| 120 custom_scale_ = scale; | |
| 121 ClampHotspot(); | |
| 122 | |
| 123 custom_data_.clear(); | |
| 124 if (data_len > 0) { | |
| 125 custom_data_.resize(data_len); | |
| 126 memcpy(&custom_data_[0], data, data_len); | |
| 127 } | |
| 128 } | |
| 129 } | |
| 130 return DeserializePlatformData(iter); | |
| 131 } | |
| 132 | |
| 133 bool WebCursor::Serialize(Pickle* pickle) const { | |
| 134 if (!pickle->WriteInt(type_) || | |
| 135 !pickle->WriteInt(hotspot_.x()) || | |
| 136 !pickle->WriteInt(hotspot_.y()) || | |
| 137 !pickle->WriteInt(custom_size_.width()) || | |
| 138 !pickle->WriteInt(custom_size_.height()) || | |
| 139 !pickle->WriteFloat(custom_scale_)) | |
| 140 return false; | |
| 141 | |
| 142 const char* data = NULL; | |
| 143 if (!custom_data_.empty()) | |
| 144 data = &custom_data_[0]; | |
| 145 if (!pickle->WriteData(data, custom_data_.size())) | |
| 146 return false; | |
| 147 | |
| 148 return SerializePlatformData(pickle); | |
| 149 } | |
| 150 | |
| 151 bool WebCursor::IsCustom() const { | |
| 152 return type_ == WebCursorInfo::TypeCustom; | |
| 153 } | |
| 154 | |
| 155 bool WebCursor::IsEqual(const WebCursor& other) const { | |
| 156 if (type_ != other.type_) | |
| 157 return false; | |
| 158 | |
| 159 if (!IsPlatformDataEqual(other)) | |
| 160 return false; | |
| 161 | |
| 162 return hotspot_ == other.hotspot_ && | |
| 163 custom_size_ == other.custom_size_ && | |
| 164 custom_scale_ == other.custom_scale_ && | |
| 165 custom_data_ == other.custom_data_; | |
| 166 } | |
| 167 | |
| 168 #if defined(OS_WIN) | |
| 169 | |
| 170 static WebCursorInfo::Type ToCursorType(HCURSOR cursor) { | |
| 171 static struct { | |
| 172 HCURSOR cursor; | |
| 173 WebCursorInfo::Type type; | |
| 174 } kStandardCursors[] = { | |
| 175 { LoadCursor(NULL, IDC_ARROW), WebCursorInfo::TypePointer }, | |
| 176 { LoadCursor(NULL, IDC_CROSS), WebCursorInfo::TypeCross }, | |
| 177 { LoadCursor(NULL, IDC_HAND), WebCursorInfo::TypeHand }, | |
| 178 { LoadCursor(NULL, IDC_IBEAM), WebCursorInfo::TypeIBeam }, | |
| 179 { LoadCursor(NULL, IDC_WAIT), WebCursorInfo::TypeWait }, | |
| 180 { LoadCursor(NULL, IDC_HELP), WebCursorInfo::TypeHelp }, | |
| 181 { LoadCursor(NULL, IDC_SIZENESW), WebCursorInfo::TypeNorthEastResize }, | |
| 182 { LoadCursor(NULL, IDC_SIZENWSE), WebCursorInfo::TypeNorthWestResize }, | |
| 183 { LoadCursor(NULL, IDC_SIZENS), WebCursorInfo::TypeNorthSouthResize }, | |
| 184 { LoadCursor(NULL, IDC_SIZEWE), WebCursorInfo::TypeEastWestResize }, | |
| 185 { LoadCursor(NULL, IDC_SIZEALL), WebCursorInfo::TypeMove }, | |
| 186 { LoadCursor(NULL, IDC_APPSTARTING), WebCursorInfo::TypeProgress }, | |
| 187 { LoadCursor(NULL, IDC_NO), WebCursorInfo::TypeNotAllowed }, | |
| 188 }; | |
| 189 for (int i = 0; i < arraysize(kStandardCursors); ++i) { | |
| 190 if (cursor == kStandardCursors[i].cursor) | |
| 191 return kStandardCursors[i].type; | |
| 192 } | |
| 193 return WebCursorInfo::TypeCustom; | |
| 194 } | |
| 195 | |
| 196 void WebCursor::InitFromExternalCursor(HCURSOR cursor) { | |
| 197 WebCursorInfo::Type cursor_type = ToCursorType(cursor); | |
| 198 | |
| 199 InitFromCursorInfo(CursorInfo(cursor_type)); | |
| 200 | |
| 201 if (cursor_type == WebCursorInfo::TypeCustom) | |
| 202 external_cursor_ = cursor; | |
| 203 } | |
| 204 | |
| 205 #endif // defined(OS_WIN) | |
| 206 | |
| 207 void WebCursor::Clear() { | |
| 208 type_ = WebCursorInfo::TypePointer; | |
| 209 hotspot_.set_x(0); | |
| 210 hotspot_.set_y(0); | |
| 211 custom_size_.set_width(0); | |
| 212 custom_size_.set_height(0); | |
| 213 custom_scale_ = 1; | |
| 214 custom_data_.clear(); | |
| 215 CleanupPlatformData(); | |
| 216 } | |
| 217 | |
| 218 void WebCursor::Copy(const WebCursor& other) { | |
| 219 type_ = other.type_; | |
| 220 hotspot_ = other.hotspot_; | |
| 221 custom_size_ = other.custom_size_; | |
| 222 custom_scale_ = other.custom_scale_; | |
| 223 custom_data_ = other.custom_data_; | |
| 224 CopyPlatformData(other); | |
| 225 } | |
| 226 | |
| 227 void WebCursor::SetCustomData(const SkBitmap& bitmap) { | |
| 228 if (bitmap.empty()) | |
| 229 return; | |
| 230 | |
| 231 // Fill custom_data_ directly with the NativeImage pixels. | |
| 232 SkAutoLockPixels bitmap_lock(bitmap); | |
| 233 custom_data_.resize(bitmap.getSize()); | |
| 234 if (!custom_data_.empty()) | |
| 235 memcpy(&custom_data_[0], bitmap.getPixels(), bitmap.getSize()); | |
| 236 custom_size_.set_width(bitmap.width()); | |
| 237 custom_size_.set_height(bitmap.height()); | |
| 238 } | |
| 239 | |
| 240 void WebCursor::ImageFromCustomData(SkBitmap* image) const { | |
| 241 if (custom_data_.empty()) | |
| 242 return; | |
| 243 | |
| 244 image->setConfig(SkBitmap::kARGB_8888_Config, | |
| 245 custom_size_.width(), | |
| 246 custom_size_.height()); | |
| 247 if (!image->allocPixels()) | |
| 248 return; | |
| 249 memcpy(image->getPixels(), &custom_data_[0], custom_data_.size()); | |
| 250 } | |
| 251 | |
| 252 void WebCursor::ClampHotspot() { | |
| 253 if (!IsCustom()) | |
| 254 return; | |
| 255 | |
| 256 // Clamp the hotspot to the custom image's dimensions. | |
| 257 hotspot_.set_x(std::max(0, | |
| 258 std::min(custom_size_.width() - 1, hotspot_.x()))); | |
| 259 hotspot_.set_y(std::max(0, | |
| 260 std::min(custom_size_.height() - 1, hotspot_.y()))); | |
| 261 } | |
| OLD | NEW |