1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/webcursor.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/pickle.h"
972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebCursorInfo;
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebImage;
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxCursorDimension = 1024;
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebCursor::WebCursor()
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : type_(WebCursorInfo::TypePointer) {
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitPlatformData();
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebCursor::WebCursor(const WebCursorInfo& cursor_info)
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : type_(WebCursorInfo::TypePointer) {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitPlatformData();
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitFromCursorInfo(cursor_info);
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebCursor::~WebCursor() {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Clear();
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebCursor::WebCursor(const WebCursor& other) {
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitPlatformData();
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Copy(other);
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst WebCursor& WebCursor::operator=(const WebCursor& other) {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (this == &other)
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *this;
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Clear();
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Copy(other);
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return *this;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::InitFromCursorInfo(const WebCursorInfo& cursor_info) {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Clear();
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cursor_info.externalHandle) {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InitFromExternalCursor(cursor_info.externalHandle);
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  type_ = cursor_info.type;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hotspot_ = cursor_info.hotSpot;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (IsCustom())
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetCustomData(cursor_info.customImage);
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClampHotspot();
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::GetCursorInfo(WebCursorInfo* cursor_info) const {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cursor_info->type = static_cast<WebCursorInfo::Type>(type_);
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cursor_info->hotSpot = hotspot_;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ImageFromCustomData(&cursor_info->customImage);
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cursor_info->externalHandle = external_cursor_;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebCursor::Deserialize(const Pickle* pickle, void** iter) {
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int type, hotspot_x, hotspot_y, size_x, size_y, data_len;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* data;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Leave |this| unmodified unless we are going to return success.
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!pickle->ReadInt(iter, &type) ||
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->ReadInt(iter, &hotspot_x) ||
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->ReadInt(iter, &hotspot_y) ||
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->ReadLength(iter, &size_x) ||
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->ReadLength(iter, &size_y) ||
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->ReadData(iter, &data, &data_len))
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ensure the size is sane, and there is enough data.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (size_x > kMaxCursorDimension ||
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_y > kMaxCursorDimension)
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  type_ = type;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (type == WebCursorInfo::TypeCustom) {
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (size_x > 0 && size_y > 0) {
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // The * 4 is because the expected format is an array of RGBA pixel
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // values.
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (size_x * size_y * 4 > data_len)
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return false;
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      hotspot_.set_x(hotspot_x);
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      hotspot_.set_y(hotspot_y);
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      custom_size_.set_width(size_x);
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      custom_size_.set_height(size_y);
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ClampHotspot();
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      custom_data_.clear();
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (data_len > 0) {
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        custom_data_.resize(data_len);
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        memcpy(&custom_data_[0], data, data_len);
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return DeserializePlatformData(pickle, iter);
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebCursor::Serialize(Pickle* pickle) const {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!pickle->WriteInt(type_) ||
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->WriteInt(hotspot_.x()) ||
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->WriteInt(hotspot_.y()) ||
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->WriteInt(custom_size_.width()) ||
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !pickle->WriteInt(custom_size_.height()))
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* data = NULL;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!custom_data_.empty())
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data = &custom_data_[0];
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!pickle->WriteData(data, custom_data_.size()))
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return SerializePlatformData(pickle);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebCursor::IsCustom() const {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return type_ == WebCursorInfo::TypeCustom;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WebCursor::IsEqual(const WebCursor& other) const {
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type_ != other.type_)
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsPlatformDataEqual(other))
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return hotspot_ == other.hotspot_ &&
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         custom_size_ == other.custom_size_ &&
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         custom_data_ == other.custom_data_;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::Clear() {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  type_ = WebCursorInfo::TypePointer;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hotspot_.set_x(0);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hotspot_.set_y(0);
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_size_.set_width(0);
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_size_.set_height(0);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_data_.clear();
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CleanupPlatformData();
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::Copy(const WebCursor& other) {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  type_ = other.type_;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hotspot_ = other.hotspot_;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_size_ = other.custom_size_;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_data_ = other.custom_data_;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CopyPlatformData(other);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if WEBKIT_USING_SKIA
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The WEBKIT_USING_CG implementation is in webcursor_mac.mm.
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::SetCustomData(const WebImage& image) {
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (image.isNull())
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Fill custom_data_ directly with the NativeImage pixels.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SkBitmap& bitmap = image.getSkBitmap();
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkAutoLockPixels bitmap_lock(bitmap);
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_data_.resize(bitmap.getSize());
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!custom_data_.empty())
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memcpy(&custom_data_[0], bitmap.getPixels(), bitmap.getSize());
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_size_.set_width(bitmap.width());
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  custom_size_.set_height(bitmap.height());
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebCursor::ImageFromCustomData(WebImage* image) const {
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (custom_data_.empty())
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap bitmap;
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   custom_size_.width(),
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   custom_size_.height());
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!bitmap.allocPixels())
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  memcpy(bitmap.getPixels(), &custom_data_[0], custom_data_.size());
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  image->assign(bitmap);
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebCursor::ClampHotspot() {
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!IsCustom())
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return;
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Clamp the hotspot to the custom image's dimensions.
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hotspot_.set_x(std::max(0,
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          std::min(custom_size_.width() - 1, hotspot_.x())));
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hotspot_.set_y(std::max(0,
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          std::min(custom_size_.height() - 1, hotspot_.y())));
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
210