[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 1 | // Copyright 2013 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 "cc/test/layer_tree_json_parser.h" |
| 6 | |
| 7 | #include "base/test/values_test_util.h" |
| 8 | #include "base/values.h" |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 9 | #include "cc/layers/content_layer.h" |
| 10 | #include "cc/layers/layer.h" |
| 11 | #include "cc/layers/nine_patch_layer.h" |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 12 | #include "cc/layers/picture_layer.h" |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 13 | #include "cc/layers/solid_color_layer.h" |
[email protected] | 3393fa9 | 2013-10-18 03:37:52 | [diff] [blame] | 14 | #include "cc/layers/texture_layer.h" |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 15 | |
| 16 | namespace cc { |
| 17 | |
| 18 | namespace { |
| 19 | |
| 20 | scoped_refptr<Layer> ParseTreeFromValue(base::Value* val, |
| 21 | ContentLayerClient* content_client) { |
[email protected] | 53b14ea | 2013-12-21 18:06:37 | [diff] [blame] | 22 | base::DictionaryValue* dict; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 23 | bool success = true; |
| 24 | success &= val->GetAsDictionary(&dict); |
| 25 | std::string layer_type; |
| 26 | success &= dict->GetString("LayerType", &layer_type); |
[email protected] | 53b14ea | 2013-12-21 18:06:37 | [diff] [blame] | 27 | base::ListValue* list; |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 28 | success &= dict->GetList("Bounds", &list); |
| 29 | int width, height; |
| 30 | success &= list->GetInteger(0, &width); |
| 31 | success &= list->GetInteger(1, &height); |
| 32 | success &= dict->GetList("Position", &list); |
| 33 | double position_x, position_y; |
| 34 | success &= list->GetDouble(0, &position_x); |
| 35 | success &= list->GetDouble(1, &position_y); |
| 36 | |
| 37 | bool draws_content; |
| 38 | success &= dict->GetBoolean("DrawsContent", &draws_content); |
| 39 | |
| 40 | scoped_refptr<Layer> new_layer; |
| 41 | if (layer_type == "SolidColorLayer") { |
[email protected] | 67be9b1d | 2013-03-08 02:27:45 | [diff] [blame] | 42 | new_layer = SolidColorLayer::Create(); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 43 | } else if (layer_type == "ContentLayer") { |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 44 | new_layer = ContentLayer::Create(content_client); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 45 | } else if (layer_type == "NinePatchLayer") { |
| 46 | success &= dict->GetList("ImageAperture", &list); |
| 47 | int aperture_x, aperture_y, aperture_width, aperture_height; |
| 48 | success &= list->GetInteger(0, &aperture_x); |
| 49 | success &= list->GetInteger(1, &aperture_y); |
| 50 | success &= list->GetInteger(2, &aperture_width); |
| 51 | success &= list->GetInteger(3, &aperture_height); |
| 52 | |
[email protected] | 53b14ea | 2013-12-21 18:06:37 | [diff] [blame] | 53 | base::ListValue* bounds; |
[email protected] | 3393fa9 | 2013-10-18 03:37:52 | [diff] [blame] | 54 | success &= dict->GetList("ImageBounds", &bounds); |
| 55 | double image_width, image_height; |
[email protected] | 89c8b48 | 2013-10-28 22:12:41 | [diff] [blame] | 56 | success &= bounds->GetDouble(0, &image_width); |
| 57 | success &= bounds->GetDouble(1, &image_height); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 58 | |
[email protected] | 741fba42 | 2013-09-20 03:34:14 | [diff] [blame] | 59 | success &= dict->GetList("Border", &list); |
| 60 | int border_x, border_y, border_width, border_height; |
| 61 | success &= list->GetInteger(0, &border_x); |
| 62 | success &= list->GetInteger(1, &border_y); |
| 63 | success &= list->GetInteger(2, &border_width); |
| 64 | success &= list->GetInteger(3, &border_height); |
| 65 | |
| 66 | bool fill_center; |
| 67 | success &= dict->GetBoolean("FillCenter", &fill_center); |
| 68 | |
[email protected] | 37adf94 | 2013-03-08 04:43:17 | [diff] [blame] | 69 | scoped_refptr<NinePatchLayer> nine_patch_layer = NinePatchLayer::Create(); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 70 | |
| 71 | SkBitmap bitmap; |
[email protected] | 0046982c | 2014-03-25 22:00:51 | [diff] [blame] | 72 | bitmap.allocN32Pixels(image_width, image_height); |
[email protected] | 741fba42 | 2013-09-20 03:34:14 | [diff] [blame] | 73 | bitmap.setImmutable(); |
[email protected] | efbdb3a | 2013-10-04 00:35:13 | [diff] [blame] | 74 | nine_patch_layer->SetBitmap(bitmap); |
| 75 | nine_patch_layer->SetAperture( |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 76 | gfx::Rect(aperture_x, aperture_y, aperture_width, aperture_height)); |
[email protected] | 741fba42 | 2013-09-20 03:34:14 | [diff] [blame] | 77 | nine_patch_layer->SetBorder( |
| 78 | gfx::Rect(border_x, border_y, border_width, border_height)); |
| 79 | nine_patch_layer->SetFillCenter(fill_center); |
| 80 | |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 81 | new_layer = nine_patch_layer; |
[email protected] | 3393fa9 | 2013-10-18 03:37:52 | [diff] [blame] | 82 | } else if (layer_type == "TextureLayer") { |
[email protected] | 89c8b48 | 2013-10-28 22:12:41 | [diff] [blame] | 83 | new_layer = TextureLayer::CreateForMailbox(NULL); |
[email protected] | a49d0f8a | 2013-05-09 23:26:19 | [diff] [blame] | 84 | } else if (layer_type == "PictureLayer") { |
| 85 | new_layer = PictureLayer::Create(content_client); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 86 | } else { // Type "Layer" or "unknown" |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 87 | new_layer = Layer::Create(); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 88 | } |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 89 | new_layer->SetPosition(gfx::PointF(position_x, position_y)); |
| 90 | new_layer->SetBounds(gfx::Size(width, height)); |
| 91 | new_layer->SetIsDrawable(draws_content); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 92 | |
| 93 | double opacity; |
| 94 | if (dict->GetDouble("Opacity", &opacity)) |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 95 | new_layer->SetOpacity(opacity); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 96 | |
[email protected] | 46c7695 | 2013-07-10 00:21:45 | [diff] [blame] | 97 | bool contents_opaque; |
| 98 | if (dict->GetBoolean("ContentsOpaque", &contents_opaque)) |
| 99 | new_layer->SetContentsOpaque(contents_opaque); |
| 100 | |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame] | 101 | bool scrollable; |
[email protected] | adeda57 | 2014-01-31 00:49:47 | [diff] [blame] | 102 | // TODO(wjmaclean) At some time in the future we may wish to test that a |
| 103 | // reconstructed layer tree contains the correct linkage for the scroll |
| 104 | // clip layer. This is complicated by the fact that the json output doesn't |
| 105 | // (currently) re-construct the tree with the same layer IDs as the original. |
| 106 | // But, since a clip layer is always an ancestor of the scrollable layer, we |
| 107 | // can just count the number of upwards hops to the clip layer and write that |
| 108 | // into the json file (with 0 hops implying no clip layer, i.e. not |
| 109 | // scrollable). Reconstructing the tree can then be accomplished by passing |
| 110 | // the parent pointer to this function and traversing the same number of |
| 111 | // ancestors to determine the pointer to the clip layer. The LayerTreesMatch() |
| 112 | // function should then check that both original and reconstructed layers |
| 113 | // have the same positioning with respect to their clip layers. |
| 114 | // |
| 115 | // For now, we can safely indicate a layer is scrollable by giving it a |
| 116 | // pointer to itself, something not normally allowed in a working tree. |
| 117 | // |
| 118 | // https://code.google.com/p/chromium/issues/detail?id=330622 |
| 119 | // |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame] | 120 | if (dict->GetBoolean("Scrollable", &scrollable)) |
[email protected] | adeda57 | 2014-01-31 00:49:47 | [diff] [blame] | 121 | new_layer->SetScrollClipLayerId(scrollable ? new_layer->id() |
| 122 | : Layer::INVALID_ID); |
[email protected] | d993e03 | 2013-06-07 00:16:16 | [diff] [blame] | 123 | |
[email protected] | 9d161d2 | 2013-10-29 20:54:10 | [diff] [blame] | 124 | bool wheel_handler; |
| 125 | if (dict->GetBoolean("WheelHandler", &wheel_handler)) |
| 126 | new_layer->SetHaveWheelEventHandlers(wheel_handler); |
| 127 | |
[email protected] | f998c53 | 2014-03-31 20:02:51 | [diff] [blame] | 128 | bool scroll_handler; |
| 129 | if (dict->GetBoolean("ScrollHandler", &scroll_handler)) |
| 130 | new_layer->SetHaveScrollEventHandlers(scroll_handler); |
| 131 | |
[email protected] | bebb1a8 | 2014-06-06 05:03:54 | [diff] [blame^] | 132 | bool is_3d_sorted; |
| 133 | if (dict->GetBoolean("Is3DSorted", &is_3d_sorted)) |
| 134 | new_layer->SetIs3dSorted(is_3d_sorted); |
| 135 | |
[email protected] | 9d161d2 | 2013-10-29 20:54:10 | [diff] [blame] | 136 | if (dict->HasKey("TouchRegion")) { |
| 137 | success &= dict->GetList("TouchRegion", &list); |
[email protected] | e51444a | 2013-12-10 23:05:01 | [diff] [blame] | 138 | Region touch_region; |
[email protected] | 9d161d2 | 2013-10-29 20:54:10 | [diff] [blame] | 139 | for (size_t i = 0; i < list->GetSize(); ) { |
| 140 | int rect_x, rect_y, rect_width, rect_height; |
| 141 | success &= list->GetInteger(i++, &rect_x); |
| 142 | success &= list->GetInteger(i++, &rect_y); |
| 143 | success &= list->GetInteger(i++, &rect_width); |
| 144 | success &= list->GetInteger(i++, &rect_height); |
| 145 | touch_region.Union(gfx::Rect(rect_x, rect_y, rect_width, rect_height)); |
| 146 | } |
| 147 | new_layer->SetTouchEventHandlerRegion(touch_region); |
| 148 | } |
| 149 | |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 150 | success &= dict->GetList("DrawTransform", &list); |
| 151 | double transform[16]; |
| 152 | for (int i = 0; i < 16; ++i) |
| 153 | success &= list->GetDouble(i, &transform[i]); |
| 154 | |
[email protected] | ed511b8d | 2013-03-25 03:29:29 | [diff] [blame] | 155 | gfx::Transform layer_transform; |
| 156 | layer_transform.matrix().setColMajord(transform); |
| 157 | new_layer->SetTransform(layer_transform); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 158 | |
| 159 | success &= dict->GetList("Children", &list); |
[email protected] | 53b14ea | 2013-12-21 18:06:37 | [diff] [blame] | 160 | for (base::ListValue::const_iterator it = list->begin(); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 161 | it != list->end(); ++it) { |
[email protected] | 7aba666 | 2013-03-12 10:17:34 | [diff] [blame] | 162 | new_layer->AddChild(ParseTreeFromValue(*it, content_client)); |
[email protected] | f8fef2bd | 2013-02-04 23:39:22 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | if (!success) |
| 166 | return NULL; |
| 167 | |
| 168 | return new_layer; |
| 169 | } |
| 170 | |
| 171 | } // namespace |
| 172 | |
| 173 | scoped_refptr<Layer> ParseTreeFromJson(std::string json, |
| 174 | ContentLayerClient* content_client) { |
| 175 | scoped_ptr<base::Value> val = base::test::ParseJson(json); |
| 176 | return ParseTreeFromValue(val.get(), content_client); |
| 177 | } |
| 178 | |
| 179 | } // namespace cc |