Add Protobuf support in cc for gfx objects

Add protobuf serialization to the following:
- gfx::Point
- gfx::PointF
- gfx::Rect
- gfx::RectF
- gfx::Size
- gfx::SizeF
- gfx::Transform

Add a helper class to handle serialization and deserialization.  Add
unit tests as well.

BUG=541321
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1394353002

Cr-Commit-Position: refs/heads/master@{#354846}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 2cd502a..2906cd0 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -312,6 +312,8 @@
     "playback/raster_source_helper.h",
     "playback/transform_display_item.cc",
     "playback/transform_display_item.h",
+    "proto/gfx_conversions.cc",
+    "proto/gfx_conversions.h",
     "quads/content_draw_quad_base.cc",
     "quads/content_draw_quad_base.h",
     "quads/debug_border_draw_quad.cc",
@@ -516,6 +518,7 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
+    "//cc/proto",
     "//cc/surfaces:surface_id",
     "//gpu",
     "//gpu/command_buffer/client:gles2_interface",
@@ -780,6 +783,7 @@
     "playback/display_item_list_unittest.cc",
     "playback/display_list_raster_source_unittest.cc",
     "playback/display_list_recording_source_unittest.cc",
+    "proto/gfx_conversions_unittest.cc",
     "quads/draw_polygon_unittest.cc",
     "quads/draw_quad_unittest.cc",
     "quads/render_pass_unittest.cc",
@@ -859,6 +863,7 @@
     ":cc",
     ":test_support",
     "//base/test:test_support",
+    "//cc/proto",
     "//cc/surfaces",
     "//cc/surfaces:surface_id",
     "//gpu",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 9070af27..5c28a9b0 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -12,11 +12,13 @@
       'target_name': 'cc',
       'type': '<(component)',
       'dependencies': [
+        'cc_proto',
         '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '<(DEPTH)/gpu/gpu.gyp:gpu',
         '<(DEPTH)/media/media.gyp:media',
         '<(DEPTH)/skia/skia.gyp:skia',
+        '<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_lite',
         '<(DEPTH)/ui/events/events.gyp:events_base',
         '<(DEPTH)/ui/gfx/gfx.gyp:gfx',
         '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
@@ -372,6 +374,8 @@
         'playback/raster_source_helper.h',
         'playback/transform_display_item.cc',
         'playback/transform_display_item.h',
+        'proto/gfx_conversions.cc',
+        'proto/gfx_conversions.h',
         'quads/content_draw_quad_base.cc',
         'quads/content_draw_quad_base.h',
         'quads/debug_border_draw_quad.cc',
@@ -572,6 +576,32 @@
       ],
     },
     {
+      # GN version: "//cc/proto"
+      'target_name': 'cc_proto',
+      'type': '<(component)',
+      'sources': [
+        'proto/point.proto',
+        'proto/pointf.proto',
+        'proto/rect.proto',
+        'proto/rectf.proto',
+        'proto/size.proto',
+        'proto/sizef.proto',
+        'proto/transform.proto',
+      ],
+      'defines': [
+        'CC_PROTO_IMPLEMENTATION=1',
+      ],
+      'variables': {
+        # Warn if clang creates exit destructors.
+        'enable_wexit_time_destructors': 1,
+        'proto_in_dir': 'proto',
+        'proto_out_dir': 'cc/proto',
+        'cc_generator_options': 'dllexport_decl=CC_PROTO_EXPORT:',
+        'cc_include': 'cc/proto/cc_proto_export.h',
+      },
+      'includes': [ '../build/protoc.gypi' ]
+    },
+    {
       # GN version: //cc/surfaces
       'target_name': 'cc_surfaces',
       'type': '<(component)',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 559786a..4941130 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -84,6 +84,7 @@
       'playback/display_item_list_unittest.cc',
       'playback/display_list_raster_source_unittest.cc',
       'playback/display_list_recording_source_unittest.cc',
+      'proto/gfx_conversions_unittest.cc',
       'quads/draw_polygon_unittest.cc',
       'quads/draw_quad_unittest.cc',
       'quads/render_pass_unittest.cc',
@@ -286,10 +287,12 @@
         '../skia/skia.gyp:skia',
         '../testing/gmock.gyp:gmock',
         '../testing/gtest.gyp:gtest',
+        '../third_party/protobuf/protobuf.gyp:protobuf_lite',
         '../ui/events/events.gyp:events_base',
         '../ui/gfx/gfx.gyp:gfx',
         '../ui/gfx/gfx.gyp:gfx_geometry',
         'cc.gyp:cc',
+        'cc.gyp:cc_proto',
         'cc.gyp:cc_surfaces',
         'cc_test_support',
       ],
diff --git a/cc/proto/BUILD.gn b/cc/proto/BUILD.gn
new file mode 100644
index 0000000..2fce37e
--- /dev/null
+++ b/cc/proto/BUILD.gn
@@ -0,0 +1,53 @@
+# 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.
+
+import("//third_party/protobuf/proto_library.gni")
+
+# Use a group here to allow external targets to depend on "cc/proto" instead of
+# cc/proto:cc_proto.  We need a group because other component targets are named
+# "proto" which breaks component builds.  A group doesn't have the same issue.
+group("proto") {
+  public_deps = [
+    ":cc_proto",
+  ]
+}
+
+component("cc_proto") {
+  # Only expose the target to the "proto" group.
+  visibility = [ ":proto" ]
+
+  public_deps = [
+    ":proto_internal",
+  ]
+}
+
+proto_library("proto_internal") {
+  # Only expose the target to the "cc_proto" target.
+  visibility = [ ":cc_proto" ]
+
+  sources = [
+    # TODO(dtrainor): Move the ui/gfx related protos to ui/gfx/proto once it is
+    # possible to include protos from other directories/targets (see
+    # crbug.com/542423).
+    "point.proto",
+    "pointf.proto",
+    "rect.proto",
+    "rectf.proto",
+    "size.proto",
+    "sizef.proto",
+    "transform.proto",
+  ]
+
+  deps = [
+    "//third_party/protobuf:protobuf_lite",
+  ]
+
+  cc_generator_options = "dllexport_decl=CC_PROTO_EXPORT:"
+  cc_include = "cc/proto/cc_proto_export.h"
+
+  defines = [ "CC_PROTO_IMPLEMENTATION" ]
+
+  # Warn if clang creates exit destructors.
+  extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
+}
diff --git a/cc/proto/cc_proto_export.h b/cc/proto/cc_proto_export.h
new file mode 100644
index 0000000..23617b3
--- /dev/null
+++ b/cc/proto/cc_proto_export.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef CC_PROTO_CC_PROTO_EXPORT_H_
+#define CC_PROTO_CC_PROTO_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(CC_PROTO_IMPLEMENTATION)
+#define CC_PROTO_EXPORT __declspec(dllexport)
+#else
+#define CC_PROTO_EXPORT __declspec(dllimport)
+#endif  // defined(CC_PROTO_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(CC_PROTO_IMPLEMENTATION)
+#define CC_PROTO_EXPORT __attribute__((visibility("default")))
+#else
+#define CC_PROTO_EXPORT
+#endif  // defined(CC_PROTO_IMPLEMENTATION)
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define CC_PROTO_EXPORT
+#endif
+
+#endif  // CC_PROTO_CC_PROTO_EXPORT_H_
diff --git a/cc/proto/gfx_conversions.cc b/cc/proto/gfx_conversions.cc
new file mode 100644
index 0000000..cf85fbf
--- /dev/null
+++ b/cc/proto/gfx_conversions.cc
@@ -0,0 +1,104 @@
+// 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 "cc/proto/gfx_conversions.h"
+
+#include "cc/proto/point.pb.h"
+#include "cc/proto/pointf.pb.h"
+#include "cc/proto/rect.pb.h"
+#include "cc/proto/rectf.pb.h"
+#include "cc/proto/size.pb.h"
+#include "cc/proto/sizef.pb.h"
+#include "cc/proto/transform.pb.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+
+void PointToProto(const gfx::Point& point, proto::Point* proto) {
+  proto->set_x(point.x());
+  proto->set_y(point.y());
+}
+
+gfx::Point ProtoToPoint(const proto::Point& proto) {
+  return gfx::Point(proto.x(), proto.y());
+}
+
+void PointFToProto(const gfx::PointF& point, proto::PointF* proto) {
+  proto->set_x(point.x());
+  proto->set_y(point.y());
+}
+
+gfx::PointF ProtoToPointF(const proto::PointF& proto) {
+  return gfx::PointF(proto.x(), proto.y());
+}
+
+void RectToProto(const gfx::Rect& rect, proto::Rect* proto) {
+  proto->mutable_origin()->set_x(rect.x());
+  proto->mutable_origin()->set_y(rect.y());
+  proto->mutable_size()->set_width(rect.width());
+  proto->mutable_size()->set_height(rect.height());
+}
+
+gfx::Rect ProtoToRect(const proto::Rect& proto) {
+  return gfx::Rect(proto.origin().x(), proto.origin().y(), proto.size().width(),
+                   proto.size().height());
+}
+
+void RectFToProto(const gfx::RectF& rect, proto::RectF* proto) {
+  proto->mutable_origin()->set_x(rect.x());
+  proto->mutable_origin()->set_y(rect.y());
+  proto->mutable_size()->set_width(rect.width());
+  proto->mutable_size()->set_height(rect.height());
+}
+
+gfx::RectF ProtoToRectF(const proto::RectF& proto) {
+  return gfx::RectF(proto.origin().x(), proto.origin().y(),
+                    proto.size().width(), proto.size().height());
+}
+
+void SizeToProto(const gfx::Size& size, proto::Size* proto) {
+  proto->set_width(size.width());
+  proto->set_height(size.height());
+}
+
+gfx::Size ProtoToSize(const proto::Size& proto) {
+  return gfx::Size(proto.width(), proto.height());
+}
+
+void SizeFToProto(const gfx::SizeF& size, proto::SizeF* proto) {
+  proto->set_width(size.width());
+  proto->set_height(size.height());
+}
+
+gfx::SizeF ProtoToSizeF(const proto::SizeF& proto) {
+  return gfx::SizeF(proto.width(), proto.height());
+}
+
+void TransformToProto(const gfx::Transform& transform,
+                      proto::Transform* proto) {
+  for (int i = 0; i < 4; i++) {
+    for (int j = 0; j < 4; j++) {
+      proto->add_matrix(transform.matrix().get(i, j));
+    }
+  }
+}
+
+gfx::Transform ProtoToTransform(const proto::Transform& proto) {
+  gfx::Transform transform;
+  DCHECK_EQ(16, proto.matrix_size());
+  for (int i = 0; i < 4; i++) {
+    for (int j = 0; j < 4; j++) {
+      transform.matrix().set(i, j, proto.matrix(i * 4 + j));
+    }
+  }
+  return transform;
+}
+
+}  // namespace cc
diff --git a/cc/proto/gfx_conversions.h b/cc/proto/gfx_conversions.h
new file mode 100644
index 0000000..e982e58
--- /dev/null
+++ b/cc/proto/gfx_conversions.h
@@ -0,0 +1,56 @@
+// 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.
+
+#ifndef CC_PROTO_GFX_CONVERSIONS_H_
+#define CC_PROTO_GFX_CONVERSIONS_H_
+
+#include "cc/base/cc_export.h"
+
+namespace gfx {
+class Point;
+class PointF;
+class Rect;
+class RectF;
+class Size;
+class SizeF;
+class Transform;
+}
+
+namespace cc {
+
+namespace proto {
+class Point;
+class PointF;
+class Rect;
+class RectF;
+class Size;
+class SizeF;
+class Transform;
+}
+
+CC_EXPORT void PointToProto(const gfx::Point& point, proto::Point* proto);
+CC_EXPORT gfx::Point ProtoToPoint(const proto::Point& proto);
+
+CC_EXPORT void PointFToProto(const gfx::PointF& point, proto::PointF* proto);
+CC_EXPORT gfx::PointF ProtoToPointF(const proto::PointF& proto);
+
+CC_EXPORT void RectToProto(const gfx::Rect& rect, proto::Rect* proto);
+CC_EXPORT gfx::Rect ProtoToRect(const proto::Rect& proto);
+
+CC_EXPORT void RectFToProto(const gfx::RectF& rect, proto::RectF* proto);
+CC_EXPORT gfx::RectF ProtoToRectF(const proto::RectF& proto);
+
+CC_EXPORT void SizeToProto(const gfx::Size& size, proto::Size* proto);
+CC_EXPORT gfx::Size ProtoToSize(const proto::Size& proto);
+
+CC_EXPORT void SizeFToProto(const gfx::SizeF& size, proto::SizeF* proto);
+CC_EXPORT gfx::SizeF ProtoToSizeF(const proto::SizeF& proto);
+
+CC_EXPORT void TransformToProto(const gfx::Transform& transform,
+                                proto::Transform* proto);
+CC_EXPORT gfx::Transform ProtoToTransform(const proto::Transform& proto);
+
+}  // namespace cc
+
+#endif  // CC_PROTO_GFX_CONVERSIONS_H_
diff --git a/cc/proto/gfx_conversions_unittest.cc b/cc/proto/gfx_conversions_unittest.cc
new file mode 100644
index 0000000..6ffdb96
--- /dev/null
+++ b/cc/proto/gfx_conversions_unittest.cc
@@ -0,0 +1,177 @@
+// 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 "cc/proto/gfx_conversions.h"
+
+#include "cc/proto/point.pb.h"
+#include "cc/proto/pointf.pb.h"
+#include "cc/proto/rect.pb.h"
+#include "cc/proto/rectf.pb.h"
+#include "cc/proto/size.pb.h"
+#include "cc/proto/sizef.pb.h"
+#include "cc/proto/transform.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+namespace {
+
+TEST(GfxProtoConversionsTest, IntSerializationLimits) {
+  // Test Point with the minimum int value.
+  {
+    gfx::Point point(std::numeric_limits<int>::min(),
+                     std::numeric_limits<int>::min());
+    proto::Point proto;
+    PointToProto(point, &proto);
+    EXPECT_EQ(point, ProtoToPoint(proto));
+  }
+
+  // Test Point with the maximum int value.
+  {
+    gfx::Point point(std::numeric_limits<int>::max(),
+                     std::numeric_limits<int>::max());
+    proto::Point proto;
+    PointToProto(point, &proto);
+    EXPECT_EQ(point, ProtoToPoint(proto));
+  }
+
+  // Test Size with the minimum int value.
+  {
+    gfx::Size size(std::numeric_limits<int>::min(),
+                   std::numeric_limits<int>::min());
+    proto::Size proto;
+    SizeToProto(size, &proto);
+    EXPECT_EQ(size, ProtoToSize(proto));
+  }
+
+  // Test Size with the maximum int value.
+  {
+    gfx::Size size(std::numeric_limits<int>::max(),
+                   std::numeric_limits<int>::max());
+    proto::Size proto;
+    SizeToProto(size, &proto);
+    EXPECT_EQ(size, ProtoToSize(proto));
+  }
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializePoint) {
+  const gfx::Point point(5, 10);
+
+  // Test PointToProto
+  proto::Point proto;
+  PointToProto(point, &proto);
+  EXPECT_EQ(point.x(), proto.x());
+  EXPECT_EQ(point.y(), proto.y());
+
+  // Test protoToPoint
+  EXPECT_EQ(point, ProtoToPoint(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializePointF) {
+  const gfx::PointF point(5.1f, 10.2f);
+
+  // Test PointFToProto
+  proto::PointF proto;
+  PointFToProto(point, &proto);
+  EXPECT_EQ(point.x(), proto.x());
+  EXPECT_EQ(point.y(), proto.y());
+
+  // Test ProtoToPointF
+  EXPECT_EQ(point, ProtoToPointF(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializeSize) {
+  const gfx::Size size(5, 10);
+
+  // Test SizeToProto
+  proto::Size proto;
+  SizeToProto(size, &proto);
+  EXPECT_EQ(size.width(), proto.width());
+  EXPECT_EQ(size.height(), proto.height());
+
+  // Test ProtoToSize
+  EXPECT_EQ(size, ProtoToSize(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializeSizeF) {
+  const gfx::SizeF size(5.1f, 10.2f);
+
+  // Test SizeFToProto
+  proto::SizeF proto;
+  SizeFToProto(size, &proto);
+  EXPECT_EQ(size.width(), proto.width());
+  EXPECT_EQ(size.height(), proto.height());
+
+  // Test ProtoToSizeF
+  EXPECT_EQ(size, ProtoToSizeF(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializeRect) {
+  const gfx::Rect rect(1, 2, 3, 4);
+
+  // Test RectToProto
+  proto::Rect proto;
+  RectToProto(rect, &proto);
+  EXPECT_EQ(rect.origin().x(), proto.origin().x());
+  EXPECT_EQ(rect.origin().y(), proto.origin().y());
+  EXPECT_EQ(rect.size().width(), proto.size().width());
+  EXPECT_EQ(rect.size().height(), proto.size().height());
+
+  // Test ProtoToRect
+  EXPECT_EQ(rect, ProtoToRect(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializeRectF) {
+  const gfx::RectF rect(1.4f, 2.3f, 3.2f, 4.1f);
+
+  // Test RectFToProto
+  proto::RectF proto;
+  RectFToProto(rect, &proto);
+  EXPECT_EQ(rect.origin().x(), proto.origin().x());
+  EXPECT_EQ(rect.origin().y(), proto.origin().y());
+  EXPECT_EQ(rect.size().width(), proto.size().width());
+  EXPECT_EQ(rect.size().height(), proto.size().height());
+
+  // Test ProtoToRectF
+  EXPECT_EQ(rect, ProtoToRectF(proto));
+}
+
+TEST(GfxProtoConversionsTest, SerializeDeserializeTransform) {
+  gfx::Transform transform(1.16f, 2.15f, 3.14f, 4.13f, 5.12f, 6.11f, 7.1f, 8.9f,
+                           9.8f, 10.7f, 11.6f, 12.5f, 13.4f, 14.3f, 15.2f,
+                           16.1f);
+
+  // Test TransformToProto
+  proto::Transform proto;
+  TransformToProto(transform, &proto);
+  EXPECT_EQ(16, proto.matrix_size());
+  EXPECT_EQ(transform.matrix().get(0, 0), proto.matrix(0));
+  EXPECT_EQ(transform.matrix().get(0, 1), proto.matrix(1));
+  EXPECT_EQ(transform.matrix().get(0, 2), proto.matrix(2));
+  EXPECT_EQ(transform.matrix().get(0, 3), proto.matrix(3));
+  EXPECT_EQ(transform.matrix().get(1, 0), proto.matrix(4));
+  EXPECT_EQ(transform.matrix().get(1, 1), proto.matrix(5));
+  EXPECT_EQ(transform.matrix().get(1, 2), proto.matrix(6));
+  EXPECT_EQ(transform.matrix().get(1, 3), proto.matrix(7));
+  EXPECT_EQ(transform.matrix().get(2, 0), proto.matrix(8));
+  EXPECT_EQ(transform.matrix().get(2, 1), proto.matrix(9));
+  EXPECT_EQ(transform.matrix().get(2, 2), proto.matrix(10));
+  EXPECT_EQ(transform.matrix().get(2, 3), proto.matrix(11));
+  EXPECT_EQ(transform.matrix().get(3, 0), proto.matrix(12));
+  EXPECT_EQ(transform.matrix().get(3, 1), proto.matrix(13));
+  EXPECT_EQ(transform.matrix().get(3, 2), proto.matrix(14));
+  EXPECT_EQ(transform.matrix().get(3, 3), proto.matrix(15));
+
+  // Test ProtoToTransform
+  EXPECT_EQ(transform, ProtoToTransform(proto));
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/proto/point.proto b/cc/proto/point.proto
new file mode 100644
index 0000000..c0c24e5
--- /dev/null
+++ b/cc/proto/point.proto
@@ -0,0 +1,14 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message Point {
+  optional int64 x = 1;
+  optional int64 y = 2;
+}
diff --git a/cc/proto/pointf.proto b/cc/proto/pointf.proto
new file mode 100644
index 0000000..e0aac584
--- /dev/null
+++ b/cc/proto/pointf.proto
@@ -0,0 +1,14 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message PointF {
+  optional float x = 1;
+  optional float y = 2;
+}
diff --git a/cc/proto/rect.proto b/cc/proto/rect.proto
new file mode 100644
index 0000000..a0194b1
--- /dev/null
+++ b/cc/proto/rect.proto
@@ -0,0 +1,17 @@
+// 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.
+
+syntax = "proto2";
+
+import "point.proto";
+import "size.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message Rect {
+  optional cc.proto.Point origin = 1;
+  optional cc.proto.Size size = 2;
+}
diff --git a/cc/proto/rectf.proto b/cc/proto/rectf.proto
new file mode 100644
index 0000000..5bd56f1
--- /dev/null
+++ b/cc/proto/rectf.proto
@@ -0,0 +1,17 @@
+// 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.
+
+syntax = "proto2";
+
+import "pointf.proto";
+import "sizef.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message RectF {
+  optional cc.proto.PointF origin = 1;
+  optional cc.proto.SizeF size = 2;
+}
diff --git a/cc/proto/size.proto b/cc/proto/size.proto
new file mode 100644
index 0000000..9cce25fa
--- /dev/null
+++ b/cc/proto/size.proto
@@ -0,0 +1,14 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message Size {
+  optional int64 width = 1;
+  optional int64 height = 2;
+}
diff --git a/cc/proto/sizef.proto b/cc/proto/sizef.proto
new file mode 100644
index 0000000..02c3c31
--- /dev/null
+++ b/cc/proto/sizef.proto
@@ -0,0 +1,14 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message SizeF {
+  optional float width = 1;
+  optional float height = 2;
+}
diff --git a/cc/proto/transform.proto b/cc/proto/transform.proto
new file mode 100644
index 0000000..68862ee4
--- /dev/null
+++ b/cc/proto/transform.proto
@@ -0,0 +1,13 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package cc.proto;
+
+message Transform {
+  repeated float matrix = 1 [packed = true];
+}