OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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/image/mojo/image_skia_struct_traits.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h" | |
11 | |
12 namespace mojo { | |
13 | |
14 namespace { | |
15 | |
16 // Strip out empty image reps. Needed because ImageSkia::image_reps does not | |
msw
2017/03/24 17:59:33
I wonder if filtering out empty image reps is an u
xiyuan
2017/03/24 18:36:53
My intention is to save some data to be transporte
| |
17 // filter out empty SkBitmap. | |
18 void GetNonemptyImageReps(const gfx::ImageSkia& image, | |
19 std::vector<gfx::ImageSkiaRep>* out_reps) { | |
20 for (auto& input_rep : image.image_reps()) { | |
21 if (!StructTraits<gfx::mojom::ImageSkiaRepDataView, | |
22 gfx::ImageSkiaRep>::IsNull(input_rep)) { | |
23 out_reps->emplace_back(input_rep); | |
24 } | |
25 } | |
26 } | |
27 | |
28 } // namespace | |
29 | |
30 StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
31 SkBitmap>::Context::Context() = default; | |
32 StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
33 SkBitmap>::Context::~Context() = default; | |
34 | |
35 // static | |
36 void* StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
37 SkBitmap>::SetUpContext(const SkBitmap& input) { | |
38 // Shared buffer is not a good way for huge images. Consider alternatives. | |
39 DCHECK_LT(input.width() * input.height(), 4000 * 4000); | |
40 | |
41 const std::vector<uint8_t> serialized_sk_bitmap( | |
42 skia::mojom::Bitmap::Serialize(&input)); | |
43 | |
44 // Use a context to serialize the bitmap to a shared buffer only once. | |
45 Context* context = new Context; | |
46 context->buffer_byte_size = serialized_sk_bitmap.size(); | |
47 context->shared_buffer_handle = | |
48 mojo::SharedBufferHandle::Create(context->buffer_byte_size); | |
49 mojo::ScopedSharedBufferMapping mapping = | |
50 context->shared_buffer_handle->Map(context->buffer_byte_size); | |
51 memcpy(mapping.get(), serialized_sk_bitmap.data(), context->buffer_byte_size); | |
52 return context; | |
53 } | |
54 | |
55 // static | |
56 void StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
57 SkBitmap>::TearDownContext(const SkBitmap& input, | |
58 void* context) { | |
59 delete static_cast<Context*>(context); | |
60 } | |
61 | |
62 // static | |
63 mojo::ScopedSharedBufferHandle | |
64 StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
65 SkBitmap>::shared_buffer_handle(const SkBitmap& input, | |
66 void* context) { | |
67 return (static_cast<Context*>(context)) | |
68 ->shared_buffer_handle->Clone( | |
69 mojo::SharedBufferHandle::AccessMode::READ_ONLY); | |
70 } | |
71 | |
72 // static | |
73 uint64_t StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | |
74 SkBitmap>::buffer_byte_size(const SkBitmap& input, | |
75 void* context) { | |
76 return (static_cast<Context*>(context))->buffer_byte_size; | |
77 } | |
78 | |
79 // static | |
80 bool StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, SkBitmap>::Read( | |
81 gfx::mojom::SharedBufferSkBitmapDataView data, | |
82 SkBitmap* out) { | |
83 mojo::ScopedSharedBufferHandle shared_buffer_handle = | |
84 data.TakeSharedBufferHandle(); | |
85 if (!shared_buffer_handle.is_valid()) | |
86 return false; | |
87 | |
88 mojo::ScopedSharedBufferMapping mapping = | |
89 shared_buffer_handle->Map(data.buffer_byte_size()); | |
90 if (!mapping) | |
91 return false; | |
92 | |
93 const std::vector<uint8_t> serialized_sk_bitmap( | |
94 static_cast<uint8_t*>(mapping.get()), | |
95 static_cast<uint8_t*>(mapping.get()) + data.buffer_byte_size()); | |
96 | |
97 return skia::mojom::Bitmap::Deserialize(serialized_sk_bitmap, out); | |
98 } | |
99 | |
100 // static | |
101 float StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep>::scale( | |
102 const gfx::ImageSkiaRep& input) { | |
103 const float scale = input.unscaled() ? 0.0f : input.scale(); | |
104 DCHECK_GE(scale, 0.0f); | |
105 | |
106 return scale; | |
107 } | |
108 | |
109 // static | |
110 bool StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep>::Read( | |
111 gfx::mojom::ImageSkiaRepDataView data, | |
112 gfx::ImageSkiaRep* out) { | |
113 // An acceptable scale must be greater than or equal to 0. | |
114 if (data.scale() < 0) | |
115 return false; | |
116 | |
117 SkBitmap bitmap; | |
118 if (!data.ReadBitmap(&bitmap)) | |
119 return false; | |
120 | |
121 *out = gfx::ImageSkiaRep(bitmap, data.scale()); | |
122 return true; | |
123 } | |
124 | |
125 // static | |
126 void* StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::SetUpContext( | |
127 const gfx::ImageSkia& input) { | |
128 // Trigger the image to load everything. | |
129 input.EnsureRepsForSupportedScales(); | |
130 | |
131 // Use a context to return a stable list of ImageSkiaRep objects. That is, | |
132 // multiple calls of image_reps() should return exactly the same list of | |
133 // ImageSkiaRep objects. So that ImageSkiaRep with the same backing pixel | |
134 // buffer is properly serialized and only once. | |
135 auto* image_reps = new std::vector<gfx::ImageSkiaRep>; | |
136 GetNonemptyImageReps(input, image_reps); | |
137 | |
138 return image_reps; | |
139 } | |
140 | |
141 // static | |
142 void StructTraits<gfx::mojom::ImageSkiaDataView, | |
143 gfx::ImageSkia>::TearDownContext(const gfx::ImageSkia& input, | |
144 void* context) { | |
145 delete static_cast<std::vector<gfx::ImageSkiaRep>*>(context); | |
146 } | |
147 | |
148 // static | |
149 const std::vector<gfx::ImageSkiaRep>& | |
150 StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps( | |
151 const gfx::ImageSkia& input, | |
152 void* context) { | |
153 // See the comment in SetUpContext regarding context usage. | |
154 return *(static_cast<std::vector<gfx::ImageSkiaRep>*>(context)); | |
155 } | |
156 | |
157 // static | |
158 bool StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::IsNull( | |
159 const gfx::ImageSkia& input) { | |
160 std::vector<gfx::ImageSkiaRep> image_reps; | |
161 GetNonemptyImageReps(input, &image_reps); | |
162 return image_reps.empty(); | |
163 } | |
164 | |
165 // static | |
166 bool StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::Read( | |
167 gfx::mojom::ImageSkiaDataView data, | |
168 gfx::ImageSkia* out) { | |
169 DCHECK(out->isNull()); | |
170 | |
171 std::vector<gfx::ImageSkiaRep> image_reps; | |
172 if (!data.ReadImageReps(&image_reps)) | |
173 return false; | |
174 | |
175 for (const auto& image_rep : image_reps) | |
176 out->AddRepresentation(image_rep); | |
177 | |
178 if (out->isNull()) | |
179 return false; | |
180 | |
181 out->SetReadOnly(); | |
182 return true; | |
183 } | |
184 | |
185 } // namespace mojo | |
OLD | NEW |