• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WebCursor()17 WebCursor::WebCursor()
18     : type_(WebCursorInfo::TypePointer) {
19   InitPlatformData();
20 }
21 
WebCursor(const WebCursorInfo & cursor_info)22 WebCursor::WebCursor(const WebCursorInfo& cursor_info)
23     : type_(WebCursorInfo::TypePointer) {
24   InitPlatformData();
25   InitFromCursorInfo(cursor_info);
26 }
27 
~WebCursor()28 WebCursor::~WebCursor() {
29   Clear();
30 }
31 
WebCursor(const WebCursor & other)32 WebCursor::WebCursor(const WebCursor& other) {
33   InitPlatformData();
34   Copy(other);
35 }
36 
operator =(const WebCursor & other)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 
InitFromCursorInfo(const WebCursorInfo & cursor_info)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 
GetCursorInfo(WebCursorInfo * cursor_info) const63 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 
Deserialize(const Pickle * pickle,void ** iter)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 
Serialize(Pickle * pickle) const117 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 
IsCustom() const134 bool WebCursor::IsCustom() const {
135   return type_ == WebCursorInfo::TypeCustom;
136 }
137 
IsEqual(const WebCursor & other) const138 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 
Clear()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 
Copy(const WebCursor & other)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.
SetCustomData(const WebImage & image)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 
ImageFromCustomData(WebImage * image) const184 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 
ClampHotspot()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