1// Copyright 2014 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 "ui/gfx/ipc/gfx_param_traits.h"
6
7#include <string>
8
9#include "third_party/skia/include/core/SkBitmap.h"
10#include "ui/gfx/rect.h"
11#include "ui/gfx/rect_f.h"
12
13namespace {
14
15struct SkBitmap_Data {
16  // The color type for the bitmap (bits per pixel, etc).
17  SkColorType fColorType;
18
19  // The alpha type for the bitmap (opaque, premul, unpremul).
20  SkAlphaType fAlphaType;
21
22  // The width of the bitmap in pixels.
23  uint32 fWidth;
24
25  // The height of the bitmap in pixels.
26  uint32 fHeight;
27
28  void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
29    const SkImageInfo& info = bitmap.info();
30    fColorType = info.fColorType;
31    fAlphaType = info.fAlphaType;
32    fWidth = info.fWidth;
33    fHeight = info.fHeight;
34  }
35
36  // Returns whether |bitmap| successfully initialized.
37  bool InitSkBitmapFromData(SkBitmap* bitmap,
38                            const char* pixels,
39                            size_t pixels_size) const {
40    if (!bitmap->tryAllocPixels(
41            SkImageInfo::Make(fWidth, fHeight, fColorType, fAlphaType)))
42      return false;
43    if (pixels_size != bitmap->getSize())
44      return false;
45    memcpy(bitmap->getPixels(), pixels, pixels_size);
46    return true;
47  }
48};
49
50}  // namespace
51
52namespace IPC {
53
54void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
55  m->WriteInt(p.x());
56  m->WriteInt(p.y());
57}
58
59bool ParamTraits<gfx::Point>::Read(const Message* m, PickleIterator* iter,
60                                   gfx::Point* r) {
61  int x, y;
62  if (!m->ReadInt(iter, &x) ||
63      !m->ReadInt(iter, &y))
64    return false;
65  r->set_x(x);
66  r->set_y(y);
67  return true;
68}
69
70void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::string* l) {
71  l->append(base::StringPrintf("(%d, %d)", p.x(), p.y()));
72}
73
74void ParamTraits<gfx::PointF>::Write(Message* m, const gfx::PointF& v) {
75  ParamTraits<float>::Write(m, v.x());
76  ParamTraits<float>::Write(m, v.y());
77}
78
79bool ParamTraits<gfx::PointF>::Read(const Message* m,
80                                      PickleIterator* iter,
81                                      gfx::PointF* r) {
82  float x, y;
83  if (!ParamTraits<float>::Read(m, iter, &x) ||
84      !ParamTraits<float>::Read(m, iter, &y))
85    return false;
86  r->set_x(x);
87  r->set_y(y);
88  return true;
89}
90
91void ParamTraits<gfx::PointF>::Log(const gfx::PointF& v, std::string* l) {
92  l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
93}
94
95void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
96  DCHECK_GE(p.width(), 0);
97  DCHECK_GE(p.height(), 0);
98  int values[2] = { p.width(), p.height() };
99  m->WriteBytes(&values, sizeof(int) * 2);
100}
101
102bool ParamTraits<gfx::Size>::Read(const Message* m,
103                                  PickleIterator* iter,
104                                  gfx::Size* r) {
105  const char* char_values;
106  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
107    return false;
108  const int* values = reinterpret_cast<const int*>(char_values);
109  if (values[0] < 0 || values[1] < 0)
110    return false;
111  r->set_width(values[0]);
112  r->set_height(values[1]);
113  return true;
114}
115
116void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
117  l->append(base::StringPrintf("(%d, %d)", p.width(), p.height()));
118}
119
120void ParamTraits<gfx::SizeF>::Write(Message* m, const gfx::SizeF& p) {
121  float values[2] = { p.width(), p.height() };
122  m->WriteBytes(&values, sizeof(float) * 2);
123}
124
125bool ParamTraits<gfx::SizeF>::Read(const Message* m,
126                                   PickleIterator* iter,
127                                   gfx::SizeF* r) {
128  const char* char_values;
129  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
130    return false;
131  const float* values = reinterpret_cast<const float*>(char_values);
132  r->set_width(values[0]);
133  r->set_height(values[1]);
134  return true;
135}
136
137void ParamTraits<gfx::SizeF>::Log(const gfx::SizeF& p, std::string* l) {
138  l->append(base::StringPrintf("(%f, %f)", p.width(), p.height()));
139}
140
141void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& p) {
142  int values[2] = { p.x(), p.y() };
143  m->WriteBytes(&values, sizeof(int) * 2);
144}
145
146bool ParamTraits<gfx::Vector2d>::Read(const Message* m,
147                                      PickleIterator* iter,
148                                      gfx::Vector2d* r) {
149  const char* char_values;
150  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
151    return false;
152  const int* values = reinterpret_cast<const int*>(char_values);
153  r->set_x(values[0]);
154  r->set_y(values[1]);
155  return true;
156}
157
158void ParamTraits<gfx::Vector2d>::Log(const gfx::Vector2d& v, std::string* l) {
159  l->append(base::StringPrintf("(%d, %d)", v.x(), v.y()));
160}
161
162void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& p) {
163  float values[2] = { p.x(), p.y() };
164  m->WriteBytes(&values, sizeof(float) * 2);
165}
166
167bool ParamTraits<gfx::Vector2dF>::Read(const Message* m,
168                                      PickleIterator* iter,
169                                      gfx::Vector2dF* r) {
170  const char* char_values;
171  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
172    return false;
173  const float* values = reinterpret_cast<const float*>(char_values);
174  r->set_x(values[0]);
175  r->set_y(values[1]);
176  return true;
177}
178
179void ParamTraits<gfx::Vector2dF>::Log(const gfx::Vector2dF& v, std::string* l) {
180  l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
181}
182
183void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
184  int values[4] = { p.x(), p.y(), p.width(), p.height() };
185  m->WriteBytes(&values, sizeof(int) * 4);
186}
187
188bool ParamTraits<gfx::Rect>::Read(const Message* m,
189                                  PickleIterator* iter,
190                                  gfx::Rect* r) {
191  const char* char_values;
192  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 4))
193    return false;
194  const int* values = reinterpret_cast<const int*>(char_values);
195  if (values[2] < 0 || values[3] < 0)
196    return false;
197  r->SetRect(values[0], values[1], values[2], values[3]);
198  return true;
199}
200
201void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
202  l->append(base::StringPrintf("(%d, %d, %d, %d)", p.x(), p.y(),
203                               p.width(), p.height()));
204}
205
206void ParamTraits<gfx::RectF>::Write(Message* m, const gfx::RectF& p) {
207  float values[4] = { p.x(), p.y(), p.width(), p.height() };
208  m->WriteBytes(&values, sizeof(float) * 4);
209}
210
211bool ParamTraits<gfx::RectF>::Read(const Message* m,
212                                   PickleIterator* iter,
213                                   gfx::RectF* r) {
214  const char* char_values;
215  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 4))
216    return false;
217  const float* values = reinterpret_cast<const float*>(char_values);
218  r->SetRect(values[0], values[1], values[2], values[3]);
219  return true;
220}
221
222void ParamTraits<gfx::RectF>::Log(const gfx::RectF& p, std::string* l) {
223  l->append(base::StringPrintf("(%f, %f, %f, %f)", p.x(), p.y(),
224                               p.width(), p.height()));
225}
226
227void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
228  size_t fixed_size = sizeof(SkBitmap_Data);
229  SkBitmap_Data bmp_data;
230  bmp_data.InitSkBitmapDataForTransfer(p);
231  m->WriteData(reinterpret_cast<const char*>(&bmp_data),
232               static_cast<int>(fixed_size));
233  size_t pixel_size = p.getSize();
234  SkAutoLockPixels p_lock(p);
235  m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
236               static_cast<int>(pixel_size));
237}
238
239bool ParamTraits<SkBitmap>::Read(const Message* m,
240                                 PickleIterator* iter,
241                                 SkBitmap* r) {
242  const char* fixed_data;
243  int fixed_data_size = 0;
244  if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
245     (fixed_data_size <= 0)) {
246    NOTREACHED();
247    return false;
248  }
249  if (fixed_data_size != sizeof(SkBitmap_Data))
250    return false;  // Message is malformed.
251
252  const char* variable_data;
253  int variable_data_size = 0;
254  if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
255     (variable_data_size < 0)) {
256    NOTREACHED();
257    return false;
258  }
259  const SkBitmap_Data* bmp_data =
260      reinterpret_cast<const SkBitmap_Data*>(fixed_data);
261  return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
262}
263
264void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::string* l) {
265  l->append("<SkBitmap>");
266}
267
268}  // namespace IPC
269