| Index: ui/gfx/image/mojo/image_skia_struct_traits.cc | 
| diff --git a/ui/gfx/image/mojo/image_skia_struct_traits.cc b/ui/gfx/image/mojo/image_skia_struct_traits.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..98ef823b9720a52e6a7216f177f38848630eb841 | 
| --- /dev/null | 
| +++ b/ui/gfx/image/mojo/image_skia_struct_traits.cc | 
| @@ -0,0 +1,158 @@ | 
| +// Copyright 2017 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 "ui/gfx/image/mojo/image_skia_struct_traits.h" | 
| + | 
| +#include <string.h> | 
| + | 
| +#include "base/logging.h" | 
| +#include "skia/public/interfaces/bitmap_skbitmap_struct_traits.h" | 
| + | 
| +namespace mojo { | 
| + | 
| +StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +             SkBitmap>::Context::Context() = default; | 
| +StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +             SkBitmap>::Context::~Context() = default; | 
| + | 
| +// static | 
| +void* StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +                   SkBitmap>::SetUpContext(const SkBitmap& input) { | 
| +  // Shared buffer is not a good way for huge images. Consider alternatives. | 
| +  DCHECK_LT(input.width() * input.height(), 4000 * 4000); | 
| + | 
| +  const std::vector<uint8_t> serialized_sk_bitmap( | 
| +      skia::mojom::Bitmap::Serialize(&input)); | 
| + | 
| +  // Use a context to serialize the bitmap to a shared buffer only once. | 
| +  Context* context = new Context; | 
| +  context->buffer_byte_size = serialized_sk_bitmap.size(); | 
| +  context->shared_buffer_handle = | 
| +      mojo::SharedBufferHandle::Create(context->buffer_byte_size); | 
| +  mojo::ScopedSharedBufferMapping mapping = | 
| +      context->shared_buffer_handle->Map(context->buffer_byte_size); | 
| +  memcpy(mapping.get(), serialized_sk_bitmap.data(), context->buffer_byte_size); | 
| +  return context; | 
| +} | 
| + | 
| +// static | 
| +void StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +                  SkBitmap>::TearDownContext(const SkBitmap& input, | 
| +                                             void* context) { | 
| +  delete static_cast<Context*>(context); | 
| +} | 
| + | 
| +// static | 
| +mojo::ScopedSharedBufferHandle | 
| +StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +             SkBitmap>::shared_buffer_handle(const SkBitmap& input, | 
| +                                             void* context) { | 
| +  return (static_cast<Context*>(context)) | 
| +      ->shared_buffer_handle->Clone( | 
| +          mojo::SharedBufferHandle::AccessMode::READ_ONLY); | 
| +} | 
| + | 
| +// static | 
| +uint64_t StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, | 
| +                      SkBitmap>::buffer_byte_size(const SkBitmap& input, | 
| +                                                  void* context) { | 
| +  return (static_cast<Context*>(context))->buffer_byte_size; | 
| +} | 
| + | 
| +// static | 
| +bool StructTraits<gfx::mojom::SharedBufferSkBitmapDataView, SkBitmap>::Read( | 
| +    gfx::mojom::SharedBufferSkBitmapDataView data, | 
| +    SkBitmap* out) { | 
| +  mojo::ScopedSharedBufferHandle shared_buffer_handle = | 
| +      data.TakeSharedBufferHandle(); | 
| +  if (!shared_buffer_handle.is_valid()) | 
| +    return false; | 
| + | 
| +  mojo::ScopedSharedBufferMapping mapping = | 
| +      shared_buffer_handle->Map(data.buffer_byte_size()); | 
| +  if (!mapping) | 
| +    return false; | 
| + | 
| +  const std::vector<uint8_t> serialized_sk_bitmap( | 
| +      static_cast<uint8_t*>(mapping.get()), | 
| +      static_cast<uint8_t*>(mapping.get()) + data.buffer_byte_size()); | 
| + | 
| +  return skia::mojom::Bitmap::Deserialize(serialized_sk_bitmap, out); | 
| +} | 
| + | 
| +// static | 
| +float StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep>::scale( | 
| +    const gfx::ImageSkiaRep& input) { | 
| +  const float scale = input.unscaled() ? 0.0f : input.scale(); | 
| +  DCHECK_GE(scale, 0.0f); | 
| + | 
| +  return scale; | 
| +} | 
| + | 
| +// static | 
| +bool StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep>::Read( | 
| +    gfx::mojom::ImageSkiaRepDataView data, | 
| +    gfx::ImageSkiaRep* out) { | 
| +  // An acceptable scale must be greater than or equal to 0. | 
| +  if (data.scale() < 0) | 
| +    return false; | 
| + | 
| +  SkBitmap bitmap; | 
| +  if (!data.ReadBitmap(&bitmap)) | 
| +    return false; | 
| + | 
| +  *out = gfx::ImageSkiaRep(bitmap, data.scale()); | 
| +  return true; | 
| +} | 
| + | 
| +// static | 
| +void* StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::SetUpContext( | 
| +    const gfx::ImageSkia& input) { | 
| +  // Trigger the image to load everything. | 
| +  input.EnsureRepsForSupportedScales(); | 
| + | 
| +  // Use a context to return a stable list of ImageSkiaRep objects. That is, | 
| +  // multiple calls of image_reps() should return exactly the same list of | 
| +  // ImageSkiaRep objects. So that ImageSkiaRep with the same backing pixel | 
| +  // buffer is properly serialized and only once. | 
| +  return new std::vector<gfx::ImageSkiaRep>(input.image_reps()); | 
| +} | 
| + | 
| +// static | 
| +void StructTraits<gfx::mojom::ImageSkiaDataView, | 
| +                  gfx::ImageSkia>::TearDownContext(const gfx::ImageSkia& input, | 
| +                                                   void* context) { | 
| +  delete static_cast<std::vector<gfx::ImageSkiaRep>*>(context); | 
| +} | 
| + | 
| +// static | 
| +const std::vector<gfx::ImageSkiaRep>& | 
| +StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps( | 
| +    const gfx::ImageSkia& input, | 
| +    void* context) { | 
| +  // See the comment in SetUpContext regarding context usage. | 
| +  return *(static_cast<std::vector<gfx::ImageSkiaRep>*>(context)); | 
| +} | 
| + | 
| +// static | 
| +bool StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::Read( | 
| +    gfx::mojom::ImageSkiaDataView data, | 
| +    gfx::ImageSkia* out) { | 
| +  DCHECK(out->isNull()); | 
| + | 
| +  std::vector<gfx::ImageSkiaRep> image_reps; | 
| +  if (!data.ReadImageReps(&image_reps)) | 
| +    return false; | 
| + | 
| +  for (const auto& image_rep : image_reps) | 
| +    out->AddRepresentation(image_rep); | 
| + | 
| +  if (out->isNull()) | 
| +    return false; | 
| + | 
| +  out->SetReadOnly(); | 
| +  return true; | 
| +} | 
| + | 
| +}  // namespace mojo | 
|  |