summaryrefslogtreecommitdiffstats
path: root/components/mus/public/cpp/lib/property_type_converters.cc
blob: 9503b9be985f9961a884645c7cd37d292c493236 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/mus/public/cpp/property_type_converters.h"

#include <stdint.h>

#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"

namespace {

// Maximum allowed height or width of a bitmap, in pixels. This limit prevents
// malformed bitmap headers from causing arbitrarily large memory allocations
// for pixel data.
const int kMaxBitmapSize = 4096;

}  // namespace

namespace mojo {

// static
std::vector<uint8_t> TypeConverter<std::vector<uint8_t>, gfx::Rect>::Convert(
    const gfx::Rect& input) {
  std::vector<uint8_t> vec(16);
  vec[0] = (input.x() >> 24) & 0xFF;
  vec[1] = (input.x() >> 16) & 0xFF;
  vec[2] = (input.x() >> 8) & 0xFF;
  vec[3] = input.x() & 0xFF;
  vec[4] = (input.y() >> 24) & 0xFF;
  vec[5] = (input.y() >> 16) & 0xFF;
  vec[6] = (input.y() >> 8) & 0xFF;
  vec[7] = input.y() & 0xFF;
  vec[8] = (input.width() >> 24) & 0xFF;
  vec[9] = (input.width() >> 16) & 0xFF;
  vec[10] = (input.width() >> 8) & 0xFF;
  vec[11] = input.width() & 0xFF;
  vec[12] = (input.height() >> 24) & 0xFF;
  vec[13] = (input.height() >> 16) & 0xFF;
  vec[14] = (input.height() >> 8) & 0xFF;
  vec[15] = input.height() & 0xFF;
  return vec;
}

// static
gfx::Rect TypeConverter<gfx::Rect, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  return gfx::Rect(
      input[0] << 24 | input[1] << 16 | input[2] << 8 | input[3],
      input[4] << 24 | input[5] << 16 | input[6] << 8 | input[7],
      input[8] << 24 | input[9] << 16 | input[10] << 8 | input[11],
      input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15]);
}

// static
std::vector<uint8_t> TypeConverter<std::vector<uint8_t>, gfx::Size>::Convert(
    const gfx::Size& input) {
  std::vector<uint8_t> vec(8);
  vec[0] = (input.width() >> 24) & 0xFF;
  vec[1] = (input.width() >> 16) & 0xFF;
  vec[2] = (input.width() >> 8) & 0xFF;
  vec[3] = input.width() & 0xFF;
  vec[4] = (input.height() >> 24) & 0xFF;
  vec[5] = (input.height() >> 16) & 0xFF;
  vec[6] = (input.height() >> 8) & 0xFF;
  vec[7] = input.height() & 0xFF;
  return vec;
}

// static
gfx::Size TypeConverter<gfx::Size, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  return gfx::Size(input[0] << 24 | input[1] << 16 | input[2] << 8 | input[3],
                   input[4] << 24 | input[5] << 16 | input[6] << 8 | input[7]);
}

// static
std::vector<uint8_t> TypeConverter<std::vector<uint8_t>, int32_t>::Convert(
    const int32_t& input) {
  std::vector<uint8_t> vec(4);
  vec[0] = (input >> 24) & 0xFF;
  vec[1] = (input >> 16) & 0xFF;
  vec[2] = (input >> 8) & 0xFF;
  vec[3] = input & 0xFF;
  return vec;
}

// static
int32_t TypeConverter<int32_t, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  return input[0] << 24 | input[1] << 16 | input[2] << 8 | input[3];
}

// static
std::vector<uint8_t>
TypeConverter<std::vector<uint8_t>, base::string16>::Convert(
    const base::string16& input) {
  return ConvertTo<std::vector<uint8_t>>(base::UTF16ToUTF8(input));
}

// static
base::string16 TypeConverter<base::string16, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  return base::UTF8ToUTF16(ConvertTo<std::string>(input));
}

// static
std::vector<uint8_t> TypeConverter<std::vector<uint8_t>, std::string>::Convert(
    const std::string& input) {
  return std::vector<uint8_t>(input.begin(), input.end());
}

// static
std::string TypeConverter<std::string, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  return std::string(input.begin(), input.end());
}

// static
std::vector<uint8_t> TypeConverter<std::vector<uint8_t>, SkBitmap>::Convert(
    const SkBitmap& input) {
  // Empty images are valid to serialize and are represented by an empty vector.
  if (input.isNull())
    return std::vector<uint8_t>();

  // Only RGBA 8888 bitmaps with premultiplied alpha are supported.
  if (input.colorType() != kBGRA_8888_SkColorType ||
      input.alphaType() != kPremul_SkAlphaType) {
    NOTREACHED();
    return std::vector<uint8_t>();
  }

  // Sanity check the bitmap size.
  int width = input.width();
  int height = input.height();
  if (width < 0 || width > kMaxBitmapSize || height < 0 ||
      height > kMaxBitmapSize) {
    NOTREACHED();
    return std::vector<uint8_t>();
  }

  // Serialize the bitmap. The size is restricted so only 2 bytes are required
  // per dimension.
  std::vector<uint8_t> vec(4 + input.getSize());
  vec[0] = (width >> 8) & 0xFF;
  vec[1] = width & 0xFF;
  vec[2] = (height >> 8) & 0xFF;
  vec[3] = height & 0xFF;
  if (!input.copyPixelsTo(&vec[4], input.getSize()))
    return std::vector<uint8_t>();
  return vec;
}

// static
SkBitmap TypeConverter<SkBitmap, std::vector<uint8_t>>::Convert(
    const std::vector<uint8_t>& input) {
  // Empty images are represented by empty vectors.
  if (input.empty())
    return SkBitmap();

  // Read and sanity check size.
  int width = input[0] << 8 | input[1];
  int height = input[2] << 8 | input[3];
  if (width < 0 || width > kMaxBitmapSize || height < 0 ||
      height > kMaxBitmapSize) {
    NOTREACHED();
    return SkBitmap();
  }

  // Try to allocate a bitmap of the appropriate size.
  SkBitmap bitmap;
  if (!bitmap.tryAllocPixels(SkImageInfo::Make(
          width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType))) {
    return SkBitmap();
  }

  // Ensure the vector contains the right amount of data.
  if (input.size() != bitmap.getSize() + 4) {
    NOTREACHED();
    return SkBitmap();
  }

  // Read the pixel data.
  SkAutoLockPixels lock(bitmap);
  memcpy(bitmap.getPixels(), &input[4], bitmap.getSize());
  return bitmap;
}

}  // namespace mojo