diff options
31 files changed, 1099 insertions, 623 deletions
diff --git a/cc/layers/nine_patch_layer.cc b/cc/layers/nine_patch_layer.cc index b500798..5e00007 100644 --- a/cc/layers/nine_patch_layer.cc +++ b/cc/layers/nine_patch_layer.cc @@ -8,16 +8,55 @@ #include "cc/resources/prioritized_resource.h" #include "cc/resources/resource_update.h" #include "cc/resources/resource_update_queue.h" +#include "cc/resources/scoped_ui_resource.h" +#include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/layer_tree_host.h" namespace cc { + +namespace { + +class ScopedUIResourceHolder : public NinePatchLayer::UIResourceHolder { + public: + static scoped_ptr<ScopedUIResourceHolder> Create(LayerTreeHost* host, + const SkBitmap& skbitmap) { + return make_scoped_ptr(new ScopedUIResourceHolder(host, skbitmap)); + } + virtual UIResourceId id() OVERRIDE { return resource_->id(); } + + private: + ScopedUIResourceHolder(LayerTreeHost* host, const SkBitmap& skbitmap) { + resource_ = ScopedUIResource::Create(host, UIResourceBitmap(skbitmap)); + } + + scoped_ptr<ScopedUIResource> resource_; +}; + +class SharedUIResourceHolder : public NinePatchLayer::UIResourceHolder { + public: + static scoped_ptr<SharedUIResourceHolder> Create(UIResourceId id) { + return make_scoped_ptr(new SharedUIResourceHolder(id)); + } + + virtual UIResourceId id() OVERRIDE { return id_; } + + private: + explicit SharedUIResourceHolder(UIResourceId id) : id_(id) {} + + UIResourceId id_; +}; + +} // anonymous namespace + + +NinePatchLayer::UIResourceHolder::~UIResourceHolder() {} + scoped_refptr<NinePatchLayer> NinePatchLayer::Create() { return make_scoped_refptr(new NinePatchLayer()); } -NinePatchLayer::NinePatchLayer() - : bitmap_dirty_(false) {} +NinePatchLayer::NinePatchLayer() : fill_center_(false) {} NinePatchLayer::~NinePatchLayer() {} @@ -26,96 +65,90 @@ scoped_ptr<LayerImpl> NinePatchLayer::CreateLayerImpl( return NinePatchLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); } -void NinePatchLayer::SetTexturePriorities( - const PriorityCalculator& priority_calc) { - if (resource_ && !resource_->texture()->resource_manager()) { - // Release the resource here, as it is no longer tied to a resource manager. - resource_.reset(); - if (!bitmap_.isNull()) - CreateResource(); - } else if (bitmap_dirty_ && DrawsContent()) { - CreateResource(); - } +void NinePatchLayer::SetLayerTreeHost(LayerTreeHost* host) { + if (host == layer_tree_host()) + return; - if (resource_) { - resource_->texture()->set_request_priority( - PriorityCalculator::UIPriority(true)); - resource_->texture()->SetDimensions( - gfx::Size(bitmap_.width(), bitmap_.height()), - layer_tree_host()->GetRendererCapabilities().best_texture_format); - } -} + Layer::SetLayerTreeHost(host); -void NinePatchLayer::SetBitmap(const SkBitmap& bitmap, gfx::Rect aperture) { - bitmap_ = bitmap; - image_aperture_ = aperture; - bitmap_dirty_ = true; - SetNeedsDisplay(); + // Recreate the resource hold against the new LTH. + RecreateUIResourceHolder(); } -bool NinePatchLayer::Update(ResourceUpdateQueue* queue, - const OcclusionTracker* occlusion) { - bool updated = Layer::Update(queue, occlusion); - - CreateUpdaterIfNeeded(); - - if (resource_ && - (bitmap_dirty_ || resource_->texture()->resource_id() == 0)) { - gfx::Rect content_rect(0, 0, bitmap_.width(), bitmap_.height()); - ResourceUpdate upload = ResourceUpdate::Create(resource_->texture(), - &bitmap_, - content_rect, - content_rect, - gfx::Vector2d()); - queue->AppendFullUpload(upload); - bitmap_dirty_ = false; - updated = true; - } +void NinePatchLayer::RecreateUIResourceHolder() { + ui_resource_holder_.reset(); + if (!layer_tree_host() || bitmap_.empty()) + return; - return updated; + ui_resource_holder_ = + ScopedUIResourceHolder::Create(layer_tree_host(), bitmap_); } -void NinePatchLayer::CreateUpdaterIfNeeded() { - if (updater_.get()) +void NinePatchLayer::SetBorder(gfx::Rect border) { + if (border == border_) return; + border_ = border; + SetNeedsCommit(); +} - updater_ = ImageLayerUpdater::Create(); +void NinePatchLayer::SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture) { + image_aperture_ = aperture; + bitmap_ = skbitmap; + + // TODO(ccameron): Remove this. This provides the default border that was + // provided before borders were required to be explicitly provided. Once Blink + // fixes its callers to call SetBorder, this can be removed. + SetBorder(gfx::Rect(aperture.x(), + aperture.y(), + skbitmap.width() - aperture.width(), + skbitmap.height() - aperture.height())); + RecreateUIResourceHolder(); + SetNeedsCommit(); } -void NinePatchLayer::CreateResource() { - DCHECK(!bitmap_.isNull()); - CreateUpdaterIfNeeded(); - updater_->SetBitmap(bitmap_); +void NinePatchLayer::SetUIResourceId(UIResourceId resource_id, + gfx::Rect aperture) { + if (ui_resource_holder_ && ui_resource_holder_->id() == resource_id && + image_aperture_ == aperture) + return; - if (!resource_) { - resource_ = updater_->CreateResource( - layer_tree_host()->contents_texture_manager()); + image_aperture_ = aperture; + if (resource_id) { + ui_resource_holder_ = SharedUIResourceHolder::Create(resource_id); + } else { + ui_resource_holder_.reset(); } + + SetNeedsCommit(); +} + +void NinePatchLayer::SetFillCenter(bool fill_center) { + if (fill_center_ == fill_center) + return; + + fill_center_ = fill_center; + SetNeedsCommit(); } bool NinePatchLayer::DrawsContent() const { - bool draws = !bitmap_.isNull() && - Layer::DrawsContent() && - bitmap_.width() && - bitmap_.height(); - return draws; + return ui_resource_holder_ && ui_resource_holder_->id() && + Layer::DrawsContent(); } void NinePatchLayer::PushPropertiesTo(LayerImpl* layer) { Layer::PushPropertiesTo(layer); NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); - if (resource_) { - DCHECK(!bitmap_.isNull()); - layer_impl->SetResourceId(resource_->texture()->resource_id()); - layer_impl->SetLayout( - gfx::Size(bitmap_.width(), bitmap_.height()), image_aperture_); - } + if (!ui_resource_holder_) { + layer_impl->SetUIResourceId(0); + } else { + DCHECK(layer_tree_host()); - // NinePatchLayer must push properties every commit to make sure - // NinePatchLayerImpl::resource_id_ is valid. - // http://crbug.com/276482 - needs_push_properties_ = true; + gfx::Size image_size = + layer_tree_host()->GetUIResourceSize(ui_resource_holder_->id()); + layer_impl->SetUIResourceId(ui_resource_holder_->id()); + layer_impl->SetLayout(image_size, image_aperture_, border_, fill_center_); + } } } // namespace cc diff --git a/cc/layers/nine_patch_layer.h b/cc/layers/nine_patch_layer.h index 35d0881..5880635 100644 --- a/cc/layers/nine_patch_layer.h +++ b/cc/layers/nine_patch_layer.h @@ -8,47 +8,60 @@ #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" #include "cc/layers/layer.h" -#include "cc/resources/image_layer_updater.h" -#include "third_party/skia/include/core/SkBitmap.h" +#include "cc/resources/ui_resource_client.h" #include "ui/gfx/rect.h" namespace cc { -class ResourceUpdateQueue; +class LayerTreeHost; +class ScopedUIResource; class CC_EXPORT NinePatchLayer : public Layer { public: static scoped_refptr<NinePatchLayer> Create(); virtual bool DrawsContent() const OVERRIDE; - virtual void SetTexturePriorities(const PriorityCalculator& priority_calc) - OVERRIDE; - virtual bool Update(ResourceUpdateQueue* queue, - const OcclusionTracker* occlusion) OVERRIDE; + virtual void PushPropertiesTo(LayerImpl* layer) OVERRIDE; + virtual void SetLayerTreeHost(LayerTreeHost* host) OVERRIDE; + + // |border| is the space around the center rectangular region in layer space + // (known as aperture in image space). |border.x()| and |border.y()| are the + // size of the left and top boundary, respectively. + // |border.width()-border.x()| and |border.height()-border.y()| are the size + // of the right and bottom boundary, respectively. + void SetBorder(gfx::Rect border); + // aperture is in the pixel space of the bitmap resource and refers to // the center patch of the ninepatch (which is unused in this // implementation). We split off eight rects surrounding it and stick them // on the edges of the layer. The corners are unscaled, the top and bottom // rects are x-stretched to fit, and the left and right rects are // y-stretched to fit. - void SetBitmap(const SkBitmap& bitmap, gfx::Rect aperture); + void SetBitmap(const SkBitmap& skbitmap, gfx::Rect aperture); + + // An alternative way of setting the resource to allow for sharing. + void SetUIResourceId(UIResourceId resource_id, gfx::Rect aperture); + void SetFillCenter(bool fill_center); + + class UIResourceHolder { + public: + virtual UIResourceId id() = 0; + virtual ~UIResourceHolder(); + }; private: NinePatchLayer(); virtual ~NinePatchLayer(); virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) OVERRIDE; + void RecreateUIResourceHolder(); - void CreateUpdaterIfNeeded(); - void CreateResource(); - - scoped_refptr<ImageLayerUpdater> updater_; - scoped_ptr<LayerUpdater::Resource> resource_; - + gfx::Rect border_; + bool fill_center_; + scoped_ptr<UIResourceHolder> ui_resource_holder_; SkBitmap bitmap_; - bool bitmap_dirty_; // The transparent center region that shows the parent layer's contents in // image space. diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc index 4274bf0..f609c3d 100644 --- a/cc/layers/nine_patch_layer_impl.cc +++ b/cc/layers/nine_patch_layer_impl.cc @@ -6,15 +6,18 @@ #include "base/strings/stringprintf.h" #include "base/values.h" +#include "cc/base/math_util.h" #include "cc/layers/quad_sink.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/trees/layer_tree_impl.h" #include "ui/gfx/rect_f.h" namespace cc { NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id) : LayerImpl(tree_impl, id), - resource_id_(0) {} + fill_center_(false), + ui_resource_id_(0) {} NinePatchLayerImpl::~NinePatchLayerImpl() {} @@ -31,11 +34,8 @@ void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) { LayerImpl::PushPropertiesTo(layer); NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); - if (!resource_id_) - return; - - layer_impl->SetResourceId(resource_id_); - layer_impl->SetLayout(image_bounds_, image_aperture_); + layer_impl->SetUIResourceId(ui_resource_id_); + layer_impl->SetLayout(image_bounds_, image_aperture_, border_, fill_center_); } static gfx::RectF NormalizedRect(float x, @@ -50,14 +50,64 @@ static gfx::RectF NormalizedRect(float x, height / total_height); } -void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds, gfx::Rect aperture) { +void NinePatchLayerImpl::SetUIResourceId(UIResourceId uid) { + if (uid == ui_resource_id_) + return; + ui_resource_id_ = uid; + NoteLayerPropertyChanged(); +} + +void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds, + gfx::Rect aperture, + gfx::Rect border, + bool fill_center) { + // This check imposes an ordering on the call sequence. An UIResource must + // exist before SetLayout can be called. + DCHECK(ui_resource_id_); + + // TODO(ccameron): the following "greater than or equal to" (GE) checks should + // be greater than (GT) to avoid degenerate nine-patches. The relaxed + // condition "equal to" is a workaround for the overhang shadow use case and + // should be investigated further. + + // |border| is in layer space. It cannot exceed the bounds of the layer. + DCHECK(!border.size().IsEmpty()); + DCHECK_GE(bounds().width(), border.width()); + DCHECK_GE(bounds().height(), border.height()); + + // Sanity Check on |border| + DCHECK_LT(border.x(), border.width()); + DCHECK_LT(border.y(), border.height()); + DCHECK_GE(border.x(), 0); + DCHECK_GE(border.y(), 0); + + // |aperture| is in image space. It cannot exceed the bounds of the bitmap. + DCHECK(!aperture.size().IsEmpty()); + DCHECK(gfx::Rect(image_bounds.width(), image_bounds.height()) + .Contains(aperture)); + + // Avoid the degenerate cases where the aperture touches the edge of the + // image. + DCHECK_LT(aperture.width(), image_bounds.width() - 1); + DCHECK_LT(aperture.height(), image_bounds.height() - 1); + DCHECK_GT(aperture.x(), 0); + DCHECK_GT(aperture.y(), 0); + + if (image_bounds_ == image_bounds && image_aperture_ == aperture && + border_ == border && fill_center_ == fill_center) + return; + image_bounds_ = image_bounds; image_aperture_ = aperture; + border_ = border; + fill_center_ = fill_center; + + NoteLayerPropertyChanged(); } bool NinePatchLayerImpl::WillDraw(DrawMode draw_mode, ResourceProvider* resource_provider) { - if (!resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) + if (!ui_resource_id_ || draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) return false; return LayerImpl::WillDraw(draw_mode, resource_provider); } @@ -68,7 +118,13 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad_sink->UseSharedQuadState(CreateSharedQuadState()); AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); - if (!resource_id_) + if (!ui_resource_id_) + return; + + ResourceProvider::ResourceId resource = + layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_); + + if (!resource) return; static const bool flipped = false; @@ -76,95 +132,106 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, DCHECK(!bounds().IsEmpty()); - // NinePatch border widths in bitmap pixel space - int left_width = image_aperture_.x(); - int top_height = image_aperture_.y(); - int right_width = image_bounds_.width() - image_aperture_.right(); - int bottom_height = image_bounds_.height() - image_aperture_.bottom(); + // NinePatch border widths in layer space. + int layer_left_width = border_.x(); + int layer_top_height = border_.y(); + int layer_right_width = border_.width() - layer_left_width; + int layer_bottom_height = border_.height() - layer_top_height; - // If layer can't fit the corners, clip to show the outer edges of the - // image. - int corner_total_width = left_width + right_width; - int middle_width = bounds().width() - corner_total_width; - if (middle_width < 0) { - float left_width_proportion = - static_cast<float>(left_width) / corner_total_width; - int left_width_crop = middle_width * left_width_proportion; - left_width += left_width_crop; - right_width = bounds().width() - left_width; - middle_width = 0; - } - int corner_total_height = top_height + bottom_height; - int middle_height = bounds().height() - corner_total_height; - if (middle_height < 0) { - float top_height_proportion = - static_cast<float>(top_height) / corner_total_height; - int top_height_crop = middle_height * top_height_proportion; - top_height += top_height_crop; - bottom_height = bounds().height() - top_height; - middle_height = 0; - } + int layer_middle_width = bounds().width() - border_.width(); + int layer_middle_height = bounds().height() - border_.height(); // Patch positions in layer space - gfx::Rect top_left(0, 0, left_width, top_height); - gfx::Rect top_right( - bounds().width() - right_width, 0, right_width, top_height); - gfx::Rect bottom_left( - 0, bounds().height() - bottom_height, left_width, bottom_height); - gfx::Rect bottom_right( - top_right.x(), bottom_left.y(), right_width, bottom_height); - gfx::Rect top(top_left.right(), 0, middle_width, top_height); - gfx::Rect left(0, top_left.bottom(), left_width, middle_height); - gfx::Rect right(top_right.x(), - top_right.bottom(), - right_width, - left.height()); - gfx::Rect bottom(top.x(), bottom_left.y(), top.width(), bottom_height); - - float img_width = image_bounds_.width(); - float img_height = image_bounds_.height(); - + gfx::Rect layer_top_left(0, 0, layer_left_width, layer_top_height); + gfx::Rect layer_top_right(bounds().width() - layer_right_width, + 0, + layer_right_width, + layer_top_height); + gfx::Rect layer_bottom_left(0, + bounds().height() - layer_bottom_height, + layer_left_width, + layer_bottom_height); + gfx::Rect layer_bottom_right(layer_top_right.x(), + layer_bottom_left.y(), + layer_right_width, + layer_bottom_height); + gfx::Rect layer_top( + layer_top_left.right(), 0, layer_middle_width, layer_top_height); + gfx::Rect layer_left( + 0, layer_top_left.bottom(), layer_left_width, layer_middle_height); + gfx::Rect layer_right(layer_top_right.x(), + layer_top_right.bottom(), + layer_right_width, + layer_left.height()); + gfx::Rect layer_bottom(layer_top.x(), + layer_bottom_left.y(), + layer_top.width(), + layer_bottom_height); + gfx::Rect layer_center(layer_left_width, + layer_top_height, + layer_middle_width, + layer_middle_height); + + // Note the following values are in image (bitmap) space. + float image_width = image_bounds_.width(); + float image_height = image_bounds_.height(); + + int image_aperture_left_width = image_aperture_.x(); + int image_aperture_top_height = image_aperture_.y(); + int image_aperture_right_width = image_width - image_aperture_.right(); + int image_aperture_bottom_height = image_height - image_aperture_.bottom(); // Patch positions in bitmap UV space (from zero to one) gfx::RectF uv_top_left = NormalizedRect(0, 0, - left_width, - top_height, - img_width, - img_height); - gfx::RectF uv_top_right = NormalizedRect(img_width - right_width, - 0, - right_width, - top_height, - img_width, - img_height); - gfx::RectF uv_bottom_left = NormalizedRect(0, - img_height - bottom_height, - left_width, - bottom_height, - img_width, - img_height); - gfx::RectF uv_bottom_right = NormalizedRect(img_width - right_width, - img_height - bottom_height, - right_width, - bottom_height, - img_width, - img_height); - gfx::RectF uv_top(uv_top_left.right(), - 0, - (img_width - left_width - right_width) / img_width, - (top_height) / img_height); + image_aperture_left_width, + image_aperture_top_height, + image_width, + image_height); + gfx::RectF uv_top_right = + NormalizedRect(image_width - image_aperture_right_width, + 0, + image_aperture_right_width, + image_aperture_top_height, + image_width, + image_height); + gfx::RectF uv_bottom_left = + NormalizedRect(0, + image_height - image_aperture_bottom_height, + image_aperture_left_width, + image_aperture_bottom_height, + image_width, + image_height); + gfx::RectF uv_bottom_right = + NormalizedRect(image_width - image_aperture_right_width, + image_height - image_aperture_bottom_height, + image_aperture_right_width, + image_aperture_bottom_height, + image_width, + image_height); + gfx::RectF uv_top( + uv_top_left.right(), + 0, + (image_width - image_aperture_left_width - image_aperture_right_width) / + image_width, + (image_aperture_top_height) / image_height); gfx::RectF uv_left(0, - uv_top_left.bottom(), - left_width / img_width, - (img_height - top_height - bottom_height) / img_height); + uv_top_left.bottom(), + image_aperture_left_width / image_width, + (image_height - image_aperture_top_height - + image_aperture_bottom_height) / + image_height); gfx::RectF uv_right(uv_top_right.x(), - uv_top_right.bottom(), - right_width / img_width, - uv_left.height()); + uv_top_right.bottom(), + image_aperture_right_width / image_width, + uv_left.height()); gfx::RectF uv_bottom(uv_top.x(), - uv_bottom_left.y(), - uv_top.width(), - bottom_height / img_height); + uv_bottom_left.y(), + uv_top.width(), + image_aperture_bottom_height / image_height); + gfx::RectF uv_center(uv_top_left.right(), + uv_top_left.bottom(), + uv_top.width(), + uv_left.height()); // Nothing is opaque here. // TODO(danakj): Should we look at the SkBitmaps to determine opaqueness? @@ -174,9 +241,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - top_left, + layer_top_left, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_top_left.origin(), uv_top_left.bottom_right(), @@ -187,9 +254,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - top_right, + layer_top_right, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_top_right.origin(), uv_top_right.bottom_right(), @@ -200,9 +267,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - bottom_left, + layer_bottom_left, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_bottom_left.origin(), uv_bottom_left.bottom_right(), @@ -213,9 +280,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - bottom_right, + layer_bottom_right, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_bottom_right.origin(), uv_bottom_right.bottom_right(), @@ -226,9 +293,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - top, + layer_top, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_top.origin(), uv_top.bottom_right(), @@ -239,9 +306,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - left, + layer_left, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_left.origin(), uv_left.bottom_right(), @@ -252,9 +319,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - right, + layer_right, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_right.origin(), uv_right.bottom_right(), @@ -265,9 +332,9 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, quad = TextureDrawQuad::Create(); quad->SetNew(shared_quad_state, - bottom, + layer_bottom, opaque_rect, - resource_id_, + resource, premultiplied_alpha, uv_bottom.origin(), uv_bottom.bottom_right(), @@ -275,10 +342,21 @@ void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, vertex_opacity, flipped); quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); -} -void NinePatchLayerImpl::DidLoseOutputSurface() { - resource_id_ = 0; + if (fill_center_) { + quad = TextureDrawQuad::Create(); + quad->SetNew(shared_quad_state, + layer_center, + opaque_rect, + resource, + premultiplied_alpha, + uv_center.origin(), + uv_center.bottom_right(), + SK_ColorTRANSPARENT, + vertex_opacity, + flipped); + quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); + } } const char* NinePatchLayerImpl::LayerTypeAsString() const { @@ -295,10 +373,12 @@ base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const { list->AppendInteger(image_aperture_.size().height()); result->Set("ImageAperture", list); - list = new base::ListValue; - list->AppendInteger(image_bounds_.width()); - list->AppendInteger(image_bounds_.height()); - result->Set("ImageBounds", list); + result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release()); + result->Set("Border", MathUtil::AsValue(border_).release()); + + base::FundamentalValue* fill_center = + base::Value::CreateBooleanValue(fill_center_); + result->Set("FillCenter", fill_center); return result; } diff --git a/cc/layers/nine_patch_layer_impl.h b/cc/layers/nine_patch_layer_impl.h index bc442d4..ba414ae 100644 --- a/cc/layers/nine_patch_layer_impl.h +++ b/cc/layers/nine_patch_layer_impl.h @@ -10,6 +10,7 @@ #include "cc/base/cc_export.h" #include "cc/layers/layer_impl.h" #include "cc/resources/resource_provider.h" +#include "cc/resources/ui_resource_client.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" @@ -27,8 +28,37 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl { } virtual ~NinePatchLayerImpl(); - void SetResourceId(unsigned id) { resource_id_ = id; } - void SetLayout(gfx::Size image_bounds, gfx::Rect aperture); + + void SetUIResourceId(UIResourceId uid); + + // The bitmap stretches out the bounds of the layer. The following picture + // illustrates the parameters associated with the dimensions. + // + // Layer space layout Bitmap space layout + // + // ------------------------ ~~~~~~~~~~ W ~~~~~~~~~~ + // | : | : : | + // | C | : Y | + // | : | : : | + // | ------------ | :~~X~~------------ | + // | | | | : | : | + // | | | | : | : | + // |~~A~~| |~~B~~| H | Q | + // | | | | : | : | + // | ------------ | : ~~~~~P~~~~~ | + // | : | : | + // | D | : | + // | : | : | + // ------------------------ ------------------------ + // + // |image_bounds| = (W, H) + // |image_aperture| = (X, Y, P, Q) + // |border| = (A, C, A + B, C + D) + // |fill_center| indicates whether to draw the center quad or not. + void SetLayout(gfx::Size image_bounds, + gfx::Rect image_aperture, + gfx::Rect border, + bool fill_center); virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) OVERRIDE; @@ -39,7 +69,6 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl { virtual void AppendQuads(QuadSink* quad_sink, AppendQuadsData* append_quads_data) OVERRIDE; virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE; - virtual void DidLoseOutputSurface() OVERRIDE; virtual base::DictionaryValue* LayerTreeAsJson() const OVERRIDE; @@ -56,7 +85,12 @@ class CC_EXPORT NinePatchLayerImpl : public LayerImpl { // image space. gfx::Rect image_aperture_; - ResourceProvider::ResourceId resource_id_; + // An inset border that the patches will be mapped to. + gfx::Rect border_; + + bool fill_center_; + + UIResourceId ui_resource_id_; DISALLOW_COPY_AND_ASSIGN(NinePatchLayerImpl); }; diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc index 1985bd4..0fbc645 100644 --- a/cc/layers/nine_patch_layer_impl_unittest.cc +++ b/cc/layers/nine_patch_layer_impl_unittest.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <stdio.h> - +#include "base/containers/hash_tables.h" #include "cc/layers/append_quads_data.h" #include "cc/layers/nine_patch_layer_impl.h" #include "cc/quads/texture_draw_quad.h" +#include "cc/resources/ui_resource_bitmap.h" +#include "cc/resources/ui_resource_client.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host_impl.h" #include "cc/test/geometry_test_utils.h" @@ -22,6 +23,40 @@ namespace cc { namespace { +class FakeUIResourceLayerTreeHostImpl : public FakeLayerTreeHostImpl { + public: + explicit FakeUIResourceLayerTreeHostImpl(Proxy* proxy) + : FakeLayerTreeHostImpl(proxy), fake_next_resource_id_(1) {} + + virtual void CreateUIResource( + UIResourceId uid, + const UIResourceBitmap& bitmap) OVERRIDE { + if (ResourceIdForUIResource(uid)) + DeleteUIResource(uid); + fake_ui_resource_map_[uid] = fake_next_resource_id_; + } + + virtual void DeleteUIResource(UIResourceId uid) OVERRIDE { + ResourceProvider::ResourceId id = ResourceIdForUIResource(uid); + if (id) + fake_ui_resource_map_.erase(uid); + } + + virtual ResourceProvider::ResourceId ResourceIdForUIResource( + UIResourceId uid) const OVERRIDE { + UIResourceMap::const_iterator iter = fake_ui_resource_map_.find(uid); + if (iter != fake_ui_resource_map_.end()) + return iter->second; + return 0; + } + + private: + ResourceProvider::ResourceId fake_next_resource_id_; + typedef base::hash_map<UIResourceId, ResourceProvider::ResourceId> + UIResourceMap; + UIResourceMap fake_ui_resource_map_; +}; + gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) { return gfx::Rect(gfx::ToRoundedInt(rect_f.x()), gfx::ToRoundedInt(rect_f.y()), @@ -29,19 +64,21 @@ gfx::Rect ToRoundedIntRect(gfx::RectF rect_f) { gfx::ToRoundedInt(rect_f.height())); } -TEST(NinePatchLayerImplTest, VerifyDrawQuads) { - // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30. - // The bounds of the layer are set to 400x400, so the draw quads - // generated should leave the border width (40) intact. +void NinePatchLayerLayoutTest(gfx::Size bitmap_size, + gfx::Rect aperture_rect, + gfx::Size layer_size, + gfx::Rect border, + bool fill_center, + size_t expected_quad_size) { MockQuadCuller quad_culler; - gfx::Size bitmap_size(100, 100); - gfx::Size layer_size(400, 400); gfx::Rect visible_content_rect(layer_size); - gfx::Rect aperture_rect(20, 30, 40, 50); - gfx::Rect scaled_aperture_non_uniform(20, 30, 340, 350); + gfx::Rect expected_remaining(border.x(), + border.y(), + layer_size.width() - border.width(), + layer_size.height() - border.height()); FakeImplProxy proxy; - FakeLayerTreeHostImpl host_impl(&proxy); + FakeUIResourceLayerTreeHostImpl host_impl(&proxy); scoped_ptr<NinePatchLayerImpl> layer = NinePatchLayerImpl::Create(host_impl.active_tree(), 1); layer->draw_properties().visible_content_rect = visible_content_rect; @@ -49,21 +86,26 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) { layer->SetContentBounds(layer_size); layer->CreateRenderSurface(); layer->draw_properties().render_target = layer.get(); - layer->SetLayout(bitmap_size, aperture_rect); - layer->SetResourceId(1); - // This scale should not affect the generated quad geometry, but only - // the shared draw transform. - gfx::Transform transform; - transform.Scale(10, 10); - layer->draw_properties().target_space_transform = transform; + UIResourceId uid = 1; + SkBitmap skbitmap; + skbitmap.setConfig( + SkBitmap::kARGB_8888_Config, bitmap_size.width(), bitmap_size.height()); + skbitmap.allocPixels(); + skbitmap.setImmutable(); + UIResourceBitmap bitmap(skbitmap); + + host_impl.CreateUIResource(uid, bitmap); + layer->SetUIResourceId(uid); + layer->SetLayout(bitmap_size, aperture_rect, border, fill_center); AppendQuadsData data; layer->AppendQuads(&quad_culler, &data); // Verify quad rects const QuadList& quads = quad_culler.quad_list(); - EXPECT_EQ(8u, quads.size()); + EXPECT_EQ(expected_quad_size, quads.size()); + Region remaining(visible_content_rect); for (size_t i = 0; i < quads.size(); ++i) { DrawQuad* quad = quads[i]; @@ -71,12 +113,16 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) { EXPECT_TRUE(visible_content_rect.Contains(quad_rect)) << i; EXPECT_TRUE(remaining.Contains(quad_rect)) << i; - EXPECT_EQ(transform, quad->quadTransform()); remaining.Subtract(Region(quad_rect)); } - EXPECT_RECT_EQ(scaled_aperture_non_uniform, remaining.bounds()); - Region scaled_aperture_region(scaled_aperture_non_uniform); - EXPECT_EQ(scaled_aperture_region, remaining); + + // Check if the left-over quad is the same size as the mapped aperture quad in + // layer space. + if (!fill_center) { + EXPECT_RECT_EQ(expected_remaining, gfx::ToEnclosedRect(remaining.bounds())); + } else { + EXPECT_TRUE(remaining.bounds().IsEmpty()); + } // Verify UV rects gfx::Rect bitmap_rect(bitmap_size); @@ -89,66 +135,59 @@ TEST(NinePatchLayerImplTest, VerifyDrawQuads) { tex_rect.Scale(bitmap_size.width(), bitmap_size.height()); tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect))); } - EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds()); - Region aperture_region(aperture_rect); - EXPECT_EQ(aperture_region, tex_remaining); -} - -TEST(NinePatchLayerImplTest, VerifyDrawQuadsForSqueezedLayer) { - // Test with a layer much smaller than the bitmap. - MockQuadCuller quad_culler; - gfx::Size bitmap_size(101, 101); - gfx::Size layer_size(51, 51); - gfx::Rect visible_content_rect(layer_size); - gfx::Rect aperture_rect(20, 30, 40, 45); // rightWidth: 40, botHeight: 25 - - FakeImplProxy proxy; - FakeLayerTreeHostImpl host_impl(&proxy); - scoped_ptr<NinePatchLayerImpl> layer = - NinePatchLayerImpl::Create(host_impl.active_tree(), 1); - layer->draw_properties().visible_content_rect = visible_content_rect; - layer->SetBounds(layer_size); - layer->SetContentBounds(layer_size); - layer->CreateRenderSurface(); - layer->draw_properties().render_target = layer.get(); - layer->SetLayout(bitmap_size, aperture_rect); - layer->SetResourceId(1); - AppendQuadsData data; - layer->AppendQuads(&quad_culler, &data); - - // Verify corner rects fill the layer and don't overlap - const QuadList& quads = quad_culler.quad_list(); - EXPECT_EQ(4u, quads.size()); - Region filled; - for (size_t i = 0; i < quads.size(); ++i) { - DrawQuad* quad = quads[i]; - gfx::Rect quad_rect = quad->rect; - - EXPECT_FALSE(filled.Intersects(quad_rect)); - filled.Union(quad_rect); + if (!fill_center) { + EXPECT_RECT_EQ(aperture_rect, tex_remaining.bounds()); + Region aperture_region(aperture_rect); + EXPECT_EQ(aperture_region, tex_remaining); + } else { + EXPECT_TRUE(remaining.bounds().IsEmpty()); } - Region expected_full(visible_content_rect); - EXPECT_EQ(expected_full, filled); +} - // Verify UV rects cover the corners of the bitmap and the crop is weighted - // proportionately to the relative corner sizes (for uneven apertures). - gfx::Rect bitmap_rect(bitmap_size); - Region tex_remaining(bitmap_rect); - for (size_t i = 0; i < quads.size(); ++i) { - DrawQuad* quad = quads[i]; - const TextureDrawQuad* tex_quad = TextureDrawQuad::MaterialCast(quad); - gfx::RectF tex_rect = - gfx::BoundingRect(tex_quad->uv_top_left, tex_quad->uv_bottom_right); - tex_rect.Scale(bitmap_size.width(), bitmap_size.height()); - tex_remaining.Subtract(Region(ToRoundedIntRect(tex_rect))); - } - Region expected_remaining_region = Region(gfx::Rect(bitmap_size)); - expected_remaining_region.Subtract(gfx::Rect(0, 0, 17, 28)); - expected_remaining_region.Subtract(gfx::Rect(67, 0, 34, 28)); - expected_remaining_region.Subtract(gfx::Rect(0, 78, 17, 23)); - expected_remaining_region.Subtract(gfx::Rect(67, 78, 34, 23)); - EXPECT_EQ(expected_remaining_region, tex_remaining); +TEST(NinePatchLayerImplTest, VerifyDrawQuads) { + // Input is a 100x100 bitmap with a 40x50 aperture at x=20, y=30. + // The bounds of the layer are set to 400x400. + gfx::Size bitmap_size(100, 100); + gfx::Size layer_size(400, 500); + gfx::Rect aperture_rect(20, 30, 40, 50); + gfx::Rect border(40, 40, 80, 80); + bool fill_center = false; + size_t expected_quad_size = 8; + NinePatchLayerLayoutTest(bitmap_size, + aperture_rect, + layer_size, + border, + fill_center, + expected_quad_size); + + // The bounds of the layer are set to less than the bitmap size. + bitmap_size = gfx::Size(100, 100); + layer_size = gfx::Size(40, 50); + aperture_rect = gfx::Rect(20, 30, 40, 50); + border = gfx::Rect(10, 10, 25, 15); + fill_center = true; + expected_quad_size = 9; + NinePatchLayerLayoutTest(bitmap_size, + aperture_rect, + layer_size, + border, + fill_center, + expected_quad_size); + + // Layer and image sizes are equal. + bitmap_size = gfx::Size(100, 100); + layer_size = gfx::Size(100, 100); + aperture_rect = gfx::Rect(20, 30, 40, 50); + border = gfx::Rect(20, 30, 40, 50); + fill_center = true; + expected_quad_size = 9; + NinePatchLayerLayoutTest(bitmap_size, + aperture_rect, + layer_size, + border, + fill_center, + expected_quad_size); } } // namespace diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc index 2e18808..101146c 100644 --- a/cc/layers/nine_patch_layer_unittest.cc +++ b/cc/layers/nine_patch_layer_unittest.cc @@ -8,6 +8,7 @@ #include "cc/resources/prioritized_resource_manager.h" #include "cc/resources/resource_provider.h" #include "cc/resources/resource_update_queue.h" +#include "cc/resources/scoped_ui_resource.h" #include "cc/scheduler/texture_uploader.h" #include "cc/test/fake_layer_tree_host_client.h" #include "cc/test/fake_output_surface.h" @@ -55,7 +56,7 @@ class NinePatchLayerTest : public testing::Test { FakeLayerTreeHostClient fake_client_; }; -TEST_F(NinePatchLayerTest, TriggerFullUploadOnceWhenChangingBitmap) { +TEST_F(NinePatchLayerTest, SetBitmap) { scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create(); ASSERT_TRUE(test_layer.get()); test_layer->SetIsDrawable(true); @@ -67,83 +68,60 @@ TEST_F(NinePatchLayerTest, TriggerFullUploadOnceWhenChangingBitmap) { layer_tree_host_->InitializeOutputSurfaceIfNeeded(); - PriorityCalculator calculator; ResourceUpdateQueue queue; OcclusionTracker occlusion_tracker(gfx::Rect(), false); - - // No bitmap set should not trigger any uploads. test_layer->SavePaintProperties(); - test_layer->SetTexturePriorities(calculator); test_layer->Update(&queue, &occlusion_tracker); - EXPECT_EQ(0u, queue.FullUploadSize()); - EXPECT_EQ(0u, queue.PartialUploadSize()); - // Setting a bitmap set should trigger a single full upload. + EXPECT_FALSE(test_layer->DrawsContent()); + SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); bitmap.allocPixels(); - test_layer->SetBitmap(bitmap, gfx::Rect(5, 5, 1, 1)); - test_layer->SavePaintProperties(); - test_layer->SetTexturePriorities(calculator); + bitmap.setImmutable(); + + gfx::Rect aperture(5, 5, 1, 1); + bool fill_center = false; + test_layer->SetBitmap(bitmap, aperture); + test_layer->SetFillCenter(fill_center); test_layer->Update(&queue, &occlusion_tracker); - EXPECT_EQ(1u, queue.FullUploadSize()); - EXPECT_EQ(0u, queue.PartialUploadSize()); - ResourceUpdate params = queue.TakeFirstFullUpload(); - EXPECT_TRUE(params.texture != NULL); - - // Upload the texture. - layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( - 1024 * 1024); - layer_tree_host_->contents_texture_manager()->PrioritizeTextures(); - - FakeOutputSurfaceClient output_surface_client; - scoped_ptr<OutputSurface> output_surface; - scoped_ptr<ResourceProvider> resource_provider; - { - DebugScopedSetImplThread impl_thread(Proxy()); - DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy()); - output_surface = FakeOutputSurface::Create3d(); - CHECK(output_surface->BindToClient(&output_surface_client)); - resource_provider = - ResourceProvider::Create(output_surface.get(), 0, false); - params.texture->AcquireBackingTexture(resource_provider.get()); - ASSERT_TRUE(params.texture->have_backing_texture()); - } - // Nothing changed, so no repeated upload. + EXPECT_TRUE(test_layer->DrawsContent()); +} + +TEST_F(NinePatchLayerTest, SetUIResourceId) { + scoped_refptr<NinePatchLayer> test_layer = NinePatchLayer::Create(); + ASSERT_TRUE(test_layer.get()); + test_layer->SetIsDrawable(true); + test_layer->SetBounds(gfx::Size(100, 100)); + + layer_tree_host_->SetRootLayer(test_layer); + Mock::VerifyAndClearExpectations(layer_tree_host_.get()); + EXPECT_EQ(test_layer->layer_tree_host(), layer_tree_host_.get()); + + layer_tree_host_->InitializeOutputSurfaceIfNeeded(); + + ResourceUpdateQueue queue; + OcclusionTracker occlusion_tracker(gfx::Rect(), false); test_layer->SavePaintProperties(); - test_layer->SetTexturePriorities(calculator); test_layer->Update(&queue, &occlusion_tracker); - EXPECT_EQ(0u, queue.FullUploadSize()); - EXPECT_EQ(0u, queue.PartialUploadSize()); - { - DebugScopedSetImplThread impl_thread(Proxy()); - DebugScopedSetMainThreadBlocked main_thread_blocked(Proxy()); - layer_tree_host_->contents_texture_manager()->ClearAllMemory( - resource_provider.get()); - } - // Reupload after eviction - test_layer->SavePaintProperties(); - test_layer->SetTexturePriorities(calculator); + EXPECT_FALSE(test_layer->DrawsContent()); + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10); + bitmap.allocPixels(); + bitmap.setImmutable(); + + scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create( + layer_tree_host_.get(), UIResourceBitmap(bitmap)); + gfx::Rect aperture(5, 5, 1, 1); + bool fill_center = true; + test_layer->SetUIResourceId(resource->id(), aperture); + test_layer->SetFillCenter(fill_center); test_layer->Update(&queue, &occlusion_tracker); - EXPECT_EQ(1u, queue.FullUploadSize()); - EXPECT_EQ(0u, queue.PartialUploadSize()); - // PrioritizedResourceManager clearing - layer_tree_host_->contents_texture_manager()->UnregisterTexture( - params.texture); - EXPECT_EQ(NULL, params.texture->resource_manager()); - test_layer->SavePaintProperties(); - test_layer->SetTexturePriorities(calculator); - ResourceUpdateQueue queue2; - test_layer->Update(&queue2, &occlusion_tracker); - EXPECT_EQ(1u, queue2.FullUploadSize()); - EXPECT_EQ(0u, queue2.PartialUploadSize()); - params = queue2.TakeFirstFullUpload(); - EXPECT_TRUE(params.texture != NULL); - EXPECT_EQ(params.texture->resource_manager(), - layer_tree_host_->contents_texture_manager()); + EXPECT_TRUE(test_layer->DrawsContent()); } } // namespace diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index f5795de..4272fe6 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc @@ -210,20 +210,14 @@ bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue, return true; } -scoped_refptr<UIResourceBitmap> PaintedScrollbarLayer::RasterizeScrollbarPart( +UIResourceBitmap PaintedScrollbarLayer::RasterizeScrollbarPart( gfx::Rect rect, ScrollbarPart part) { DCHECK(!rect.size().IsEmpty()); - scoped_refptr<UIResourceBitmap> bitmap = - UIResourceBitmap::Create(new uint8_t[rect.width() * rect.height() * 4], - UIResourceBitmap::RGBA8, - UIResourceBitmap::CLAMP_TO_EDGE, - rect.size()); - SkBitmap skbitmap; skbitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); - skbitmap.setPixels(bitmap->GetPixels()); + skbitmap.allocPixels(); SkCanvas skcanvas(skbitmap); skcanvas.translate(SkFloatToScalar(-rect.x()), SkFloatToScalar(-rect.y())); @@ -240,8 +234,11 @@ scoped_refptr<UIResourceBitmap> PaintedScrollbarLayer::RasterizeScrollbarPart( skcanvas.clipRect(layer_skrect); scrollbar_->PaintPart(&skcanvas, part, layer_rect); + // Make sure that the pixels are no longer mutable to unavoid unnecessary + // allocation and copying. + skbitmap.setImmutable(); - return bitmap; + return UIResourceBitmap(skbitmap); } } // namespace cc diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h index 8140f8c..e84377d 100644 --- a/cc/layers/painted_scrollbar_layer.h +++ b/cc/layers/painted_scrollbar_layer.h @@ -68,8 +68,8 @@ class CC_EXPORT PaintedScrollbarLayer : public ScrollbarLayerInterface, int MaxTextureSize(); float ClampScaleToMaxTextureSize(float scale); - scoped_refptr<UIResourceBitmap> RasterizeScrollbarPart(gfx::Rect rect, - ScrollbarPart part); + UIResourceBitmap RasterizeScrollbarPart(gfx::Rect rect, + ScrollbarPart part); scoped_ptr<Scrollbar> scrollbar_; int scroll_layer_id_; diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index e62a032d..2e1b4b6 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc @@ -525,7 +525,8 @@ class MockLayerTreeHost : public LayerTreeHost { virtual UIResourceId CreateUIResource(UIResourceClient* content) OVERRIDE { total_ui_resource_created_++; UIResourceId nid = next_id_++; - ui_resource_bitmap_map_[nid] = content->GetBitmap(nid, false); + ui_resource_bitmap_map_.insert( + std::make_pair(nid, content->GetBitmap(nid, false))); return nid; } @@ -544,13 +545,13 @@ class MockLayerTreeHost : public LayerTreeHost { gfx::Size ui_resource_size(UIResourceId id) { UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); - if (iter != ui_resource_bitmap_map_.end() && iter->second.get()) - return iter->second->GetSize(); + if (iter != ui_resource_bitmap_map_.end()) + return iter->second.GetSize(); return gfx::Size(); } private: - typedef base::hash_map<UIResourceId, scoped_refptr<UIResourceBitmap> > + typedef base::hash_map<UIResourceId, UIResourceBitmap> UIResourceBitmapMap; UIResourceBitmapMap ui_resource_bitmap_map_; diff --git a/cc/resources/scoped_ui_resource.cc b/cc/resources/scoped_ui_resource.cc index 0136a8e..e69b4bc 100644 --- a/cc/resources/scoped_ui_resource.cc +++ b/cc/resources/scoped_ui_resource.cc @@ -12,12 +12,12 @@ namespace cc { scoped_ptr<ScopedUIResource> ScopedUIResource::Create( LayerTreeHost* host, - scoped_refptr<UIResourceBitmap> bitmap) { + const UIResourceBitmap& bitmap) { return make_scoped_ptr(new ScopedUIResource(host, bitmap)); } ScopedUIResource::ScopedUIResource(LayerTreeHost* host, - scoped_refptr<UIResourceBitmap> bitmap) + const UIResourceBitmap& bitmap) : bitmap_(bitmap), host_(host) { DCHECK(host_); id_ = host_->CreateUIResource(this); @@ -32,16 +32,9 @@ ScopedUIResource::~ScopedUIResource() { } } -gfx::Size ScopedUIResource::GetSize() const { - return bitmap_->GetSize(); -} - -scoped_refptr<UIResourceBitmap> ScopedUIResource::GetBitmap( - UIResourceId uid, - bool resource_lost) { +UIResourceBitmap ScopedUIResource::GetBitmap(UIResourceId uid, + bool resource_lost) { return bitmap_; } -ScopedUIResource::ScopedUIResource() {} - } // namespace cc diff --git a/cc/resources/scoped_ui_resource.h b/cc/resources/scoped_ui_resource.h index a4525e6..c257e1e 100644 --- a/cc/resources/scoped_ui_resource.h +++ b/cc/resources/scoped_ui_resource.h @@ -15,28 +15,27 @@ namespace cc { class LayerTreeHost; +// ScopedUIResource creates an UIResource from a bitmap and a LayerTreeHost. +// This class holds a pointer to the host so that when the instance goes out of +// scope, the created resource is deleted. On a GetBitmap call from the +// UIResource manager, ScopeUIResource always returns the reference to the +// initially given bitmap regardless of whether the request was due to lost +// resource or not. class CC_EXPORT ScopedUIResource : public UIResourceClient { public: - static scoped_ptr<ScopedUIResource> Create( - LayerTreeHost* host, - scoped_refptr<UIResourceBitmap> bitmap); + static scoped_ptr<ScopedUIResource> Create(LayerTreeHost* host, + const UIResourceBitmap& bitmap); virtual ~ScopedUIResource(); - gfx::Size GetSize() const; - // UIResourceClient implementation. - virtual scoped_refptr<UIResourceBitmap> GetBitmap( - UIResourceId uid, - bool resource_lost) OVERRIDE; + virtual UIResourceBitmap GetBitmap(UIResourceId uid, + bool resource_lost) OVERRIDE; UIResourceId id() { return id_; } protected: - ScopedUIResource(LayerTreeHost* host, scoped_refptr<UIResourceBitmap> bitmap); - - // An empty default contructor for testing. - ScopedUIResource(); + ScopedUIResource(LayerTreeHost* host, const UIResourceBitmap& bitmap); - scoped_refptr<UIResourceBitmap> bitmap_; + UIResourceBitmap bitmap_; LayerTreeHost* host_; UIResourceId id_; diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc index 1510607d..2acbd95 100644 --- a/cc/resources/ui_resource_bitmap.cc +++ b/cc/resources/ui_resource_bitmap.cc @@ -4,25 +4,45 @@ #include "cc/resources/ui_resource_bitmap.h" +#include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace cc { -scoped_refptr<UIResourceBitmap> -UIResourceBitmap::Create(uint8_t* pixels, - UIResourceFormat format, - UIResourceWrapMode wrap_mode, - gfx::Size size) { - scoped_refptr<UIResourceBitmap> ret = new UIResourceBitmap(); - ret->pixels_ = scoped_ptr<uint8_t[]>(pixels); - ret->format_ = format; - ret->wrap_mode_ = wrap_mode; - ret->size_ = size; - - return ret; +uint8_t* UIResourceBitmap::GetPixels() const { + if (!pixel_ref_) + return NULL; + return static_cast<uint8_t*>(pixel_ref_->pixels()); +} + +void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref, + UIResourceFormat format, + UIResourceWrapMode wrap_mode, + gfx::Size size) { + DCHECK(size.width()); + DCHECK(size.height()); + DCHECK(pixel_ref); + DCHECK(pixel_ref->isImmutable()); + format_ = format; + wrap_mode_ = wrap_mode; + size_ = size; + pixel_ref_ = pixel_ref; +} + +UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap, + UIResourceWrapMode wrap_mode) { + DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config); + DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels()); + DCHECK(skbitmap.isImmutable()); + + skia::RefPtr<SkPixelRef> pixel_ref = skia::SharePtr(skbitmap.pixelRef()); + Create(pixel_ref, + UIResourceBitmap::RGBA8, + wrap_mode, + gfx::Size(skbitmap.width(), skbitmap.height())); } -UIResourceBitmap::UIResourceBitmap() {} UIResourceBitmap::~UIResourceBitmap() {} } // namespace cc diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h index e1b5aee..f10fed9 100644 --- a/cc/resources/ui_resource_bitmap.h +++ b/cc/resources/ui_resource_bitmap.h @@ -8,16 +8,20 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "cc/base/cc_export.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/core/SkPixelRef.h" #include "third_party/skia/include/core/SkTypes.h" #include "ui/gfx/size.h" +class SkBitmap; + namespace cc { -// Ref-counted bitmap class (can’t use SkBitmap because of ETC1). Thread-safety -// ensures that both main and impl threads can hold references to the bitmap and -// that asynchronous uploads are allowed. -class CC_EXPORT UIResourceBitmap - : public base::RefCountedThreadSafe<UIResourceBitmap> { +// A bitmap class that contains a ref-counted reference to a SkPixelRef* that +// holds the content of the bitmap (cannot use SkBitmap because of ETC1). +// Thread-safety (by ways of SkPixelRef) ensures that both main and impl threads +// can hold references to the bitmap and that asynchronous uploads are allowed. +class CC_EXPORT UIResourceBitmap { public: enum UIResourceFormat { RGBA8 @@ -27,29 +31,29 @@ class CC_EXPORT UIResourceBitmap REPEAT }; - // Takes ownership of “pixels”. - static scoped_refptr<UIResourceBitmap> Create(uint8_t* pixels, - UIResourceFormat format, - UIResourceWrapMode wrap_mode, - gfx::Size size); - gfx::Size GetSize() const { return size_; } UIResourceFormat GetFormat() const { return format_; } UIResourceWrapMode GetWrapMode() const { return wrap_mode_; } - uint8_t* GetPixels() { return pixels_.get(); } + uint8_t* GetPixels() const; - private: - friend class base::RefCountedThreadSafe<UIResourceBitmap>; + // The constructor for the UIResourceBitmap. User must ensure that |skbitmap| + // is immutable. The SkBitmap format should be in 32-bit RGBA. Wrap mode is + // unnecessary for most UI resources and is defaulted to CLAMP_TO_EDGE. + UIResourceBitmap(const SkBitmap& skbitmap, + UIResourceWrapMode wrap_mode = CLAMP_TO_EDGE); - UIResourceBitmap(); ~UIResourceBitmap(); - scoped_ptr<uint8_t[]> pixels_; + private: + void Create(const skia::RefPtr<SkPixelRef>& pixel_ref, + UIResourceFormat format, + UIResourceWrapMode wrap_mode, + gfx::Size size); + + skia::RefPtr<SkPixelRef> pixel_ref_; UIResourceFormat format_; UIResourceWrapMode wrap_mode_; gfx::Size size_; - - DISALLOW_COPY_AND_ASSIGN(UIResourceBitmap); }; } // namespace cc diff --git a/cc/resources/ui_resource_client.h b/cc/resources/ui_resource_client.h index d647936..24309a5 100644 --- a/cc/resources/ui_resource_client.h +++ b/cc/resources/ui_resource_client.h @@ -24,8 +24,8 @@ class CC_EXPORT UIResourceClient { // delete a UIResourceClient object after DeleteUIResource has been called for // all IDs associated with it. A valid bitmap always must be returned but it // doesn't need to be the same size or format as the original. - virtual scoped_refptr<UIResourceBitmap> GetBitmap(UIResourceId uid, - bool resource_lost) = 0; + virtual UIResourceBitmap GetBitmap(UIResourceId uid, + bool resource_lost) = 0; virtual ~UIResourceClient() {} }; diff --git a/cc/test/data/10_10_layer_tree.json b/cc/test/data/10_10_layer_tree.json index e2d7071..be624e5 100644 --- a/cc/test/data/10_10_layer_tree.json +++ b/cc/test/data/10_10_layer_tree.json @@ -14,21 +14,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, -55.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -52,21 +56,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 200, 200 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 7.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ -8.0, -8.0 ] }, { - "Bounds": [ 0, 0 ], + "Bounds": [ 4, 4 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 0.0, 0.0 ] @@ -110,21 +118,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 51 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, -47.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -140,9 +152,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 15.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -150,11 +164,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 23.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 38, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -206,21 +222,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 82 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, -5.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -236,9 +256,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 57.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -246,11 +268,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 65.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -302,21 +326,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 110 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 132.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -332,9 +360,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 194.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -342,11 +372,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 202.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -398,21 +430,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 124 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 356.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -428,9 +464,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 418.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -438,11 +476,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 426.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -494,21 +534,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 124 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 625.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -524,9 +568,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 687.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -534,11 +580,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 695.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -590,19 +638,23 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 56 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 894.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.024660587310791, 0.0, 0.0, 0.0, 0.0, 1.024660587310791, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 118.47874069213867, 149.62063217163086, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -620,9 +672,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 956.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -630,11 +684,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 859.8399658203125, 964.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -686,21 +742,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 952.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -716,9 +776,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 1014.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -726,11 +788,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 384.8399658203125, 1001.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 231.8399658203125, 0.0 ] @@ -774,21 +838,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 960.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -804,9 +872,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 1022.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -814,11 +884,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 384.8399658203125, 951.828857421875, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 231.8399658203125, 0.0 ] @@ -862,21 +934,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 568.0, 968.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -900,21 +976,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 620.0, 1030.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ -8.0, -8.0 ] }, { - "Bounds": [ 0, 0 ], + "Bounds": [ 3, 3 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 0.0, 0.0 ] @@ -958,21 +1038,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, -55.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -996,9 +1080,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 7.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1006,11 +1092,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 15.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1054,21 +1142,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 45 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, -47.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1084,9 +1176,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 15.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1094,11 +1188,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 23.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1150,21 +1246,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 75 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, -25.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1180,9 +1280,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 37.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1190,11 +1292,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 45.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1246,21 +1350,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 103 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 91.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1276,9 +1384,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 153.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1286,11 +1396,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 161.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1342,21 +1454,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 123 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 295.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1372,9 +1488,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 357.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1382,11 +1500,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 365.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1438,21 +1558,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 124 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 561.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1468,9 +1592,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 623.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1478,11 +1604,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 631.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1534,21 +1662,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 77 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 830.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1580,9 +1712,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 892.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1590,11 +1724,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 900.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1646,21 +1782,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 952.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1676,9 +1816,11 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 1014.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", @@ -1686,11 +1828,13 @@ "Position": [ -8.0, -8.0 ] }, { "Bounds": [ 306, 60 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 261.8399658203125, 1012.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 38, 0, 0, 0 ], - "ImageBounds": [ 39, 1 ], + "FillCenter": false, + "ImageAperture": [ 37, 1, 1, 1 ], + "ImageBounds": [ 39, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 231.8399658203125, 0.0 ] @@ -1734,21 +1878,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 960.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1764,21 +1912,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 1022.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ -8.0, -8.0 ] }, { - "Bounds": [ 0, 0 ], + "Bounds": [ 3, 3 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 0.0, 0.0 ] @@ -1822,21 +1974,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 210, 40 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 3.125, 0.0, 0.0, 0.0, 0.0, 3.125, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -30.0, 968.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 32, 32, 0, 0 ], + "FillCenter": false, + "ImageAperture": [ 31, 31, 1, 1 ], "ImageBounds": [ 33, 33 ], "LayerType": "NinePatchLayer", "Opacity": 0.5, "Position": [ -60.0, -70.0 ] }, { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ -8.0, -8.0 ] @@ -1852,21 +2008,25 @@ "Bounds": [ 0, 0 ], "Children": [ { "Bounds": [ 553, 791 ], + "Border": [ 1, 1, 20, 20 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 22.0, 1030.0, 0.0, 1.0 ], "DrawsContent": true, + "FillCenter": false, "ImageAperture": [ 17, 35, 2, 1 ], "ImageBounds": [ 20, 37 ], "LayerType": "NinePatchLayer", "Opacity": 1.0, "Position": [ -8.0, -8.0 ] }, { - "Bounds": [ 0, 0 ], + "Bounds": [ 3, 3 ], + "Border": [ 1, 1, 2, 2 ], "Children": [ ], "DrawTransform": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ], "DrawsContent": true, - "ImageAperture": [ 0, 0, 0, 0 ], - "ImageBounds": [ 1, 1 ], + "FillCenter": false, + "ImageAperture": [ 1, 1, 1, 1 ], + "ImageBounds": [ 3, 3 ], "LayerType": "NinePatchLayer", "Opacity": 0.0, "Position": [ 0.0, 0.0 ] diff --git a/cc/test/fake_scoped_ui_resource.cc b/cc/test/fake_scoped_ui_resource.cc index ce5ee11..bf86f54 100644 --- a/cc/test/fake_scoped_ui_resource.cc +++ b/cc/test/fake_scoped_ui_resource.cc @@ -8,25 +8,34 @@ namespace cc { +namespace { + +UIResourceBitmap CreateMockUIResourceBitmap() { + SkBitmap skbitmap; + skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); + skbitmap.allocPixels(); + skbitmap.setImmutable(); + return UIResourceBitmap(skbitmap); +} + +} // anonymous namespace + scoped_ptr<FakeScopedUIResource> FakeScopedUIResource::Create( LayerTreeHost* host) { return make_scoped_ptr(new FakeScopedUIResource(host)); } -FakeScopedUIResource::FakeScopedUIResource(LayerTreeHost* host) { +FakeScopedUIResource::FakeScopedUIResource(LayerTreeHost* host) + : ScopedUIResource(host, CreateMockUIResourceBitmap()) { + // The constructor of ScopedUIResource already created a resource so we need + // to delete the created resource to wipe the state clean. + host_->DeleteUIResource(id_); ResetCounters(); - bitmap_ = UIResourceBitmap::Create( - new uint8_t[1], - UIResourceBitmap::RGBA8, - UIResourceBitmap::CLAMP_TO_EDGE, - gfx::Size(1, 1)); - host_ = host; id_ = host_->CreateUIResource(this); } -scoped_refptr<UIResourceBitmap> FakeScopedUIResource::GetBitmap( - UIResourceId uid, - bool resource_lost) { +UIResourceBitmap FakeScopedUIResource::GetBitmap(UIResourceId uid, + bool resource_lost) { resource_create_count++; if (resource_lost) lost_resource_count++; diff --git a/cc/test/fake_scoped_ui_resource.h b/cc/test/fake_scoped_ui_resource.h index 84c097f..970d7b0 100644 --- a/cc/test/fake_scoped_ui_resource.h +++ b/cc/test/fake_scoped_ui_resource.h @@ -16,9 +16,8 @@ class FakeScopedUIResource : public ScopedUIResource { public: static scoped_ptr<FakeScopedUIResource> Create(LayerTreeHost* host); - virtual scoped_refptr<UIResourceBitmap> GetBitmap( - UIResourceId uid, - bool resource_lost) OVERRIDE; + virtual UIResourceBitmap GetBitmap(UIResourceId uid, + bool resource_lost) OVERRIDE; void ResetCounters(); int resource_create_count; diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc index 51c421f..1c47e1e 100644 --- a/cc/test/layer_tree_json_parser.cc +++ b/cc/test/layer_tree_json_parser.cc @@ -54,14 +54,29 @@ scoped_refptr<Layer> ParseTreeFromValue(base::Value* val, success &= list->GetInteger(0, &image_width); success &= list->GetInteger(1, &image_height); + success &= dict->GetList("Border", &list); + int border_x, border_y, border_width, border_height; + success &= list->GetInteger(0, &border_x); + success &= list->GetInteger(1, &border_y); + success &= list->GetInteger(2, &border_width); + success &= list->GetInteger(3, &border_height); + + bool fill_center; + success &= dict->GetBoolean("FillCenter", &fill_center); + scoped_refptr<NinePatchLayer> nine_patch_layer = NinePatchLayer::Create(); SkBitmap bitmap; bitmap.setConfig(SkBitmap::kARGB_8888_Config, image_width, image_height); bitmap.allocPixels(NULL, NULL); + bitmap.setImmutable(); nine_patch_layer->SetBitmap(bitmap, gfx::Rect(aperture_x, aperture_y, aperture_width, aperture_height)); + nine_patch_layer->SetBorder( + gfx::Rect(border_x, border_y, border_width, border_height)); + nine_patch_layer->SetFillCenter(fill_center); + new_layer = nine_patch_layer; } else if (layer_type == "PictureLayer") { new_layer = PictureLayer::Create(content_client); diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 8afb592..7c06b96 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc @@ -61,8 +61,31 @@ RendererCapabilities::RendererCapabilities() RendererCapabilities::~RendererCapabilities() {} -UIResourceRequest::UIResourceRequest() - : type(UIResourceInvalidRequest), id(0), bitmap(NULL) {} +UIResourceRequest::UIResourceRequest(UIResourceRequestType type, + UIResourceId id) + : type_(type), id_(id) {} + +UIResourceRequest::UIResourceRequest(UIResourceRequestType type, + UIResourceId id, + const UIResourceBitmap& bitmap) + : type_(type), id_(id), bitmap_(new UIResourceBitmap(bitmap)) {} + +UIResourceRequest::UIResourceRequest(const UIResourceRequest& request) { + (*this) = request; +} + +UIResourceRequest& UIResourceRequest::operator=( + const UIResourceRequest& request) { + type_ = request.type_; + id_ = request.id_; + if (request.bitmap_) { + bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get())); + } else { + bitmap_.reset(); + } + + return *this; +} UIResourceRequest::~UIResourceRequest() {} @@ -389,7 +412,7 @@ void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) { if (overhang_ui_resource_) { host_impl->SetOverhangUIResource( overhang_ui_resource_->id(), - overhang_ui_resource_->GetSize()); + GetUIResourceSize(overhang_ui_resource_->id())); } DCHECK(!sync_tree->ViewportSizeInvalid()); @@ -647,16 +670,16 @@ void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) { DCHECK(bitmap.width() && bitmap.height()); DCHECK_EQ(bitmap.bytesPerPixel(), 4); - scoped_refptr<UIResourceBitmap> overhang_ui_bitmap(UIResourceBitmap::Create( - new uint8_t[bitmap.width() * bitmap.height() * bitmap.bytesPerPixel()], - UIResourceBitmap::RGBA8, - UIResourceBitmap::REPEAT, - gfx::Size(bitmap.width(), bitmap.height()))); - bitmap.copyPixelsTo( - overhang_ui_bitmap->GetPixels(), - bitmap.width() * bitmap.height() * bitmap.bytesPerPixel(), - bitmap.width() * bitmap.bytesPerPixel()); - overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_ui_bitmap); + SkBitmap bitmap_copy; + if (bitmap.isImmutable()) { + bitmap_copy = bitmap; + } else { + bitmap.copyTo(&bitmap_copy, bitmap.config()); + bitmap_copy.setImmutable(); + } + + overhang_ui_resource_ = ScopedUIResource::Create( + this, UIResourceBitmap(bitmap_copy, UIResourceBitmap::REPEAT)); } void LayerTreeHost::SetVisible(bool visible) { @@ -1162,18 +1185,22 @@ void LayerTreeHost::AnimateLayers(base::TimeTicks time) { UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) { DCHECK(client); - UIResourceRequest request; - bool resource_lost = false; - request.type = UIResourceRequest::UIResourceCreate; - request.id = next_ui_resource_id_++; - - DCHECK(ui_resource_client_map_.find(request.id) == + UIResourceId next_id = next_ui_resource_id_++; + DCHECK(ui_resource_client_map_.find(next_id) == ui_resource_client_map_.end()); - request.bitmap = client->GetBitmap(request.id, resource_lost); + bool resource_lost = false; + UIResourceRequest request(UIResourceRequest::UIResourceCreate, + next_id, + client->GetBitmap(next_id, resource_lost)); ui_resource_request_queue_.push_back(request); - ui_resource_client_map_[request.id] = client; - return request.id; + + UIResourceClientData data; + data.client = client; + data.size = request.GetBitmap().GetSize(); + + ui_resource_client_map_[request.GetId()] = data; + return request.GetId(); } // Deletes a UI resource. May safely be called more than once. @@ -1182,11 +1209,9 @@ void LayerTreeHost::DeleteUIResource(UIResourceId uid) { if (iter == ui_resource_client_map_.end()) return; - UIResourceRequest request; - request.type = UIResourceRequest::UIResourceDelete; - request.id = uid; + UIResourceRequest request(UIResourceRequest::UIResourceDelete, uid); ui_resource_request_queue_.push_back(request); - ui_resource_client_map_.erase(uid); + ui_resource_client_map_.erase(iter); } void LayerTreeHost::RecreateUIResources() { @@ -1194,16 +1219,25 @@ void LayerTreeHost::RecreateUIResources() { iter != ui_resource_client_map_.end(); ++iter) { UIResourceId uid = iter->first; - UIResourceRequest request; - request.type = UIResourceRequest::UIResourceCreate; - request.id = uid; + const UIResourceClientData& data = iter->second; bool resource_lost = true; - request.bitmap = iter->second->GetBitmap(uid, resource_lost); - DCHECK(request.bitmap.get()); + UIResourceRequest request(UIResourceRequest::UIResourceCreate, + uid, + data.client->GetBitmap(uid, resource_lost)); ui_resource_request_queue_.push_back(request); } } +// Returns the size of a resource given its id. +gfx::Size LayerTreeHost::GetUIResourceSize(UIResourceId uid) const { + UIResourceClientMap::const_iterator iter = ui_resource_client_map_.find(uid); + if (iter == ui_resource_client_map_.end()) + return gfx::Size(); + + const UIResourceClientData& data = iter->second; + return data.size; +} + void LayerTreeHost::RegisterViewportLayers( scoped_refptr<Layer> page_scale_layer, scoped_refptr<Layer> inner_viewport_scroll_layer, diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index fff226a..e2e33d2 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h @@ -87,18 +87,35 @@ struct CC_EXPORT RendererCapabilities { bool using_discard_framebuffer; }; -struct CC_EXPORT UIResourceRequest { +class CC_EXPORT UIResourceRequest { + public: enum UIResourceRequestType { UIResourceCreate, UIResourceDelete, UIResourceInvalidRequest }; - UIResourceRequest(); + UIResourceRequest(UIResourceRequestType type, UIResourceId id); + UIResourceRequest(UIResourceRequestType type, + UIResourceId id, + const UIResourceBitmap& bitmap); + UIResourceRequest(const UIResourceRequest& request); + ~UIResourceRequest(); - UIResourceRequestType type; - UIResourceId id; - scoped_refptr<UIResourceBitmap> bitmap; + + UIResourceRequestType GetType() const { return type_; } + UIResourceId GetId() const { return id_; } + UIResourceBitmap GetBitmap() const { + DCHECK(bitmap_); + return *bitmap_.get(); + } + + UIResourceRequest& operator=(const UIResourceRequest& request); + + private: + UIResourceRequestType type_; + UIResourceId id_; + scoped_ptr<UIResourceBitmap> bitmap_; }; class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { @@ -295,6 +312,8 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { // were evicted on the impl thread. void RecreateUIResources(); + virtual gfx::Size GetUIResourceSize(UIResourceId id) const; + bool UsingSharedMemoryResources(); int id() const { return tree_id_; } @@ -331,7 +350,13 @@ class CC_EXPORT LayerTreeHost : NON_EXPORTED_BASE(public RateLimiterClient) { bool AnimateLayersRecursive(Layer* current, base::TimeTicks time); - typedef base::hash_map<UIResourceId, UIResourceClient*> UIResourceClientMap; + struct UIResourceClientData { + UIResourceClient* client; + gfx::Size size; + }; + + typedef base::hash_map<UIResourceId, UIResourceClientData> + UIResourceClientMap; UIResourceClientMap ui_resource_client_map_; int next_ui_resource_id_; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 3a95b5b..97ceea5 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -2629,14 +2629,13 @@ void LayerTreeHostImpl::SetDebugState( SetFullRootLayerDamage(); } -void LayerTreeHostImpl::CreateUIResource( - UIResourceId uid, - scoped_refptr<UIResourceBitmap> bitmap) { +void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, + const UIResourceBitmap& bitmap) { DCHECK_GT(uid, 0); - DCHECK_EQ(bitmap->GetFormat(), UIResourceBitmap::RGBA8); + DCHECK_EQ(bitmap.GetFormat(), UIResourceBitmap::RGBA8); GLint wrap_mode = 0; - switch (bitmap->GetWrapMode()) { + switch (bitmap.GetWrapMode()) { case UIResourceBitmap::CLAMP_TO_EDGE: wrap_mode = GL_CLAMP_TO_EDGE; break; @@ -2651,16 +2650,16 @@ void LayerTreeHostImpl::CreateUIResource( if (id) DeleteUIResource(uid); id = resource_provider_->CreateResource( - bitmap->GetSize(), + bitmap.GetSize(), wrap_mode, ResourceProvider::TextureUsageAny, resource_provider_->best_texture_format()); ui_resource_map_[uid] = id; resource_provider_->SetPixels(id, - reinterpret_cast<uint8_t*>(bitmap->GetPixels()), - gfx::Rect(bitmap->GetSize()), - gfx::Rect(bitmap->GetSize()), + bitmap.GetPixels(), + gfx::Rect(bitmap.GetSize()), + gfx::Rect(bitmap.GetSize()), gfx::Vector2d(0, 0)); MarkUIResourceNotEvicted(uid); } diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index e747d7b..7ea6cc9 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -50,8 +50,8 @@ class RenderPassDrawQuad; class TextureMailboxDeleter; class TopControlsManager; class UIResourceBitmap; +class UIResourceRequest; struct RendererCapabilities; -struct UIResourceRequest; // LayerTreeHost->Proxy callback interface. class LayerTreeHostImplClient { @@ -400,14 +400,15 @@ class CC_EXPORT LayerTreeHostImpl bool page_scale_animation_active() const { return !!page_scale_animation_; } - void CreateUIResource(UIResourceId uid, - scoped_refptr<UIResourceBitmap> bitmap); + virtual void CreateUIResource(UIResourceId uid, + const UIResourceBitmap& bitmap); // Deletes a UI resource. May safely be called more than once. - void DeleteUIResource(UIResourceId uid); + virtual void DeleteUIResource(UIResourceId uid); void EvictAllUIResources(); bool EvictedUIResourcesExist() const; - ResourceProvider::ResourceId ResourceIdForUIResource(UIResourceId uid) const; + virtual ResourceProvider::ResourceId ResourceIdForUIResource( + UIResourceId uid) const; void DidInitializeVisibleTileForTesting() { DidInitializeVisibleTile(); } diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index d386795..c184c67 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -3075,12 +3075,13 @@ TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredOverhangBitmap) { host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_)); SetupActiveTreeLayers(); + SkBitmap skbitmap; + skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2); + skbitmap.allocPixels(); + skbitmap.setImmutable(); + // Specify an overhang bitmap to use. - scoped_refptr<UIResourceBitmap> ui_resource_bitmap(UIResourceBitmap::Create( - new uint8_t[4], - UIResourceBitmap::RGBA8, - UIResourceBitmap::REPEAT, - gfx::Size(1, 1))); + UIResourceBitmap ui_resource_bitmap(skbitmap, UIResourceBitmap::REPEAT); UIResourceId ui_resource_id = 12345; host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap); host_impl_->SetOverhangUIResource(ui_resource_id, gfx::Size(32, 32)); @@ -6547,12 +6548,13 @@ TEST_F(LayerTreeHostImplTest, UIResourceManagement) { EXPECT_EQ(0u, context3d->NumTextures()); + SkBitmap skbitmap; + skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); + skbitmap.allocPixels(); + skbitmap.setImmutable(); + UIResourceId ui_resource_id = 1; - scoped_refptr<UIResourceBitmap> bitmap = UIResourceBitmap::Create( - new uint8_t[1], - UIResourceBitmap::RGBA8, - UIResourceBitmap::CLAMP_TO_EDGE, - gfx::Size(1, 1)); + UIResourceBitmap bitmap(skbitmap); host_impl_->CreateUIResource(ui_resource_id, bitmap); EXPECT_EQ(1u, context3d->NumTextures()); ResourceProvider::ResourceId id1 = diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 4c1034a..280bdad 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc @@ -657,12 +657,12 @@ void LayerTreeImpl::ProcessUIResourceRequestQueue() { UIResourceRequest req = ui_resource_request_queue_.front(); ui_resource_request_queue_.pop_front(); - switch (req.type) { + switch (req.GetType()) { case UIResourceRequest::UIResourceCreate: - layer_tree_host_impl_->CreateUIResource(req.id, req.bitmap); + layer_tree_host_impl_->CreateUIResource(req.GetId(), req.GetBitmap()); break; case UIResourceRequest::UIResourceDelete: - layer_tree_host_impl_->DeleteUIResource(req.id); + layer_tree_host_impl_->DeleteUIResource(req.GetId()); break; case UIResourceRequest::UIResourceInvalidRequest: NOTREACHED(); diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 9464d95..7c66759 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h @@ -42,8 +42,8 @@ class PaintTimeCounter; class Proxy; class ResourceProvider; class TileManager; +class UIResourceRequest; struct RendererCapabilities; -struct UIResourceRequest; typedef std::list<UIResourceRequest> UIResourceRequestQueue; diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 313764b..7f4f064 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -22,6 +22,8 @@ #include "cc/output/compositor_frame.h" #include "cc/output/context_provider.h" #include "cc/output/output_surface.h" +#include "cc/resources/scoped_ui_resource.h" +#include "cc/resources/ui_resource_bitmap.h" #include "cc/trees/layer_tree_host.h" #include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "content/browser/gpu/gpu_surface_tracker.h" @@ -233,7 +235,9 @@ void CompositorImpl::SetSurface(jobject surface) { void CompositorImpl::SetVisible(bool visible) { if (!visible) { + ui_resource_map_.clear(); host_.reset(); + client_->UIResourcesAreInvalid(); } else if (!host_) { cc::LayerTreeSettings settings; settings.refresh_rate = 60.0; @@ -260,6 +264,9 @@ void CompositorImpl::SetVisible(bool visible) { host_->SetLayerTreeHostClientReady(); host_->SetViewportSize(size_); host_->set_has_transparent_background(has_transparent_background_); + // Need to recreate the UI resources because a new LayerTreeHost has been + // created. + client_->DidLoseUIResources(); } } @@ -291,6 +298,23 @@ bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { return false; } +cc::UIResourceId CompositorImpl::GenerateUIResource( + const cc::UIResourceBitmap& bitmap) { + if (!host_) + return 0; + scoped_ptr<cc::ScopedUIResource> ui_resource = + cc::ScopedUIResource::Create(host_.get(), bitmap); + cc::UIResourceId id = ui_resource->id(); + ui_resource_map_.set(id, ui_resource.Pass()); + return id; +} + +void CompositorImpl::DeleteUIResource(cc::UIResourceId resource_id) { + UIResourceMap::iterator it = ui_resource_map_.find(resource_id); + if (it != ui_resource_map_.end()) + ui_resource_map_.erase(it); +} + WebKit::WebGLId CompositorImpl::GenerateTexture(gfx::JavaBitmap& bitmap) { unsigned int texture_id = BuildBasicTexture(); WebKit::WebGraphicsContext3D* context = diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h index 845e830a..58e44c8 100644 --- a/content/browser/renderer_host/compositor_impl_android.h +++ b/content/browser/renderer_host/compositor_impl_android.h @@ -7,8 +7,10 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "cc/resources/ui_resource_client.h" #include "cc/trees/layer_tree_host_client.h" #include "content/browser/renderer_host/image_transport_factory_android.h" #include "content/common/content_export.h" @@ -21,6 +23,7 @@ namespace cc { class InputHandlerClient; class Layer; class LayerTreeHost; +class ScopedUIResource; } namespace content { @@ -60,6 +63,9 @@ class CONTENT_EXPORT CompositorImpl void *pixels, const gfx::Rect& rect) OVERRIDE; virtual void SetNeedsRedraw() OVERRIDE; virtual void Composite() OVERRIDE; + virtual cc::UIResourceId GenerateUIResource( + const cc::UIResourceBitmap& bitmap) OVERRIDE; + virtual void DeleteUIResource(cc::UIResourceId resource_id) OVERRIDE; virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) OVERRIDE; virtual WebKit::WebGLId GenerateCompressedTexture( gfx::Size& size, int data_size, void* data) OVERRIDE; @@ -117,6 +123,10 @@ class CONTENT_EXPORT CompositorImpl scoped_refptr<cc::ContextProvider> null_offscreen_context_provider_; + typedef base::ScopedPtrHashMap<cc::UIResourceId, cc::ScopedUIResource> + UIResourceMap; + UIResourceMap ui_resource_map_; + DISALLOW_COPY_AND_ASSIGN(CompositorImpl); }; diff --git a/content/public/browser/android/compositor.h b/content/public/browser/android/compositor.h index c1cc997..a7072c4 100644 --- a/content/public/browser/android/compositor.h +++ b/content/public/browser/android/compositor.h @@ -6,6 +6,8 @@ #define CONTENT_PUBLIC_BROWSER_ANDROID_COMPOSITOR_H_ #include "base/callback.h" +#include "cc/resources/ui_resource_bitmap.h" +#include "cc/resources/ui_resource_client.h" #include "content/common/content_export.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" @@ -84,6 +86,13 @@ class CONTENT_EXPORT Compositor { // Composite immediately. Used in single-threaded mode. virtual void Composite() = 0; + // Generates a UIResource and returns a UIResourceId. May return 0. + virtual cc::UIResourceId GenerateUIResource( + const cc::UIResourceBitmap& bitmap) = 0; + + // Deletes a UIResource. + virtual void DeleteUIResource(cc::UIResourceId resource_id) = 0; + // Generates an OpenGL texture and returns a texture handle. May return 0 // if the current context is lost. virtual WebKit::WebGLId GenerateTexture(gfx::JavaBitmap& bitmap) = 0; diff --git a/content/public/browser/android/compositor_client.h b/content/public/browser/android/compositor_client.h index d70f0c0..d835de1 100644 --- a/content/public/browser/android/compositor_client.h +++ b/content/public/browser/android/compositor_client.h @@ -23,6 +23,12 @@ class CONTENT_EXPORT CompositorClient { // Tells the client that GL resources were lost and need to be reinitialized. virtual void DidLoseResources() {} + // Tells the client that UI resources were lost and need to be reinitialized. + virtual void DidLoseUIResources() {} + + // Mark the UI Resources as being invalid for use. + virtual void UIResourcesAreInvalid() {} + protected: CompositorClient() {} virtual ~CompositorClient() {} diff --git a/ui/gfx/android/java_bitmap.cc b/ui/gfx/android/java_bitmap.cc index c3cd94d..6c2eaa8 100644 --- a/ui/gfx/android/java_bitmap.cc +++ b/ui/gfx/android/java_bitmap.cc @@ -62,33 +62,20 @@ ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) { return jbitmap; } -static ScopedJavaLocalRef<jobject> CreateJavaBitmapFromResource( - const char* name, gfx::Size requested_size) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> jname( - base::android::ConvertUTF8ToJavaString(env, name)); - return ui::Java_BitmapHelper_decodeDrawableResource(env, - jname.obj(), - requested_size.width(), - requested_size.height()); -} - -static SkBitmap ConvertToSkBitmap(ScopedJavaLocalRef<jobject> jbitmap) { - if (jbitmap.is_null()) - return SkBitmap(); +SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap) { + DCHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888); - JavaBitmap src_lock(jbitmap.obj()); - DCHECK_EQ(src_lock.format(), ANDROID_BITMAP_FORMAT_RGBA_8888); - - gfx::Size src_size = src_lock.size(); + gfx::Size src_size = jbitmap.size(); SkBitmap skbitmap; skbitmap.setConfig(SkBitmap::kARGB_8888_Config, - src_size.width(), src_size.height(), src_lock.stride()); + src_size.width(), + src_size.height(), + jbitmap.stride()); skbitmap.allocPixels(); SkAutoLockPixels dst_lock(skbitmap); - void* src_pixels = src_lock.pixels(); + void* src_pixels = jbitmap.pixels(); void* dst_pixels = skbitmap.getPixels(); memcpy(dst_pixels, src_pixels, skbitmap.getSize()); @@ -98,14 +85,17 @@ static SkBitmap ConvertToSkBitmap(ScopedJavaLocalRef<jobject> jbitmap) { SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size) { DCHECK(!size.IsEmpty()); - SkBitmap bitmap = - ConvertToSkBitmap(CreateJavaBitmapFromResource(name, size)); - if (bitmap.isNull()) - return bitmap; - // RESIZE_BOX has sufficient downsampling quality with minimal runtime cost. - return skia::ImageOperations::Resize(bitmap, - skia::ImageOperations::RESIZE_BOX, - size.width(), size.height()); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name)); + ScopedJavaLocalRef<jobject> jobj(ui::Java_BitmapHelper_decodeDrawableResource( + env, jname.obj(), size.width(), size.height())); + if (jobj.is_null()) + return SkBitmap(); + + JavaBitmap jbitmap(jobj.obj()); + SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(jbitmap); + return skia::ImageOperations::Resize( + bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height()); } } // namespace gfx diff --git a/ui/gfx/android/java_bitmap.h b/ui/gfx/android/java_bitmap.h index 14bfc990..319ad79 100644 --- a/ui/gfx/android/java_bitmap.h +++ b/ui/gfx/android/java_bitmap.h @@ -44,6 +44,8 @@ class UI_EXPORT JavaBitmap { UI_EXPORT base::android::ScopedJavaLocalRef<jobject> ConvertToJavaBitmap( const SkBitmap* skbitmap); +UI_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap); + // If the resource loads successfully, it will be resized to |size|. // Note: If the source resource is smaller than |size|, quality may suffer. UI_EXPORT SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size); |