summaryrefslogtreecommitdiff
path: root/chromium/cc/layers/nine_patch_layer_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/cc/layers/nine_patch_layer_impl.cc')
-rw-r--r--chromium/cc/layers/nine_patch_layer_impl.cc307
1 files changed, 194 insertions, 113 deletions
diff --git a/chromium/cc/layers/nine_patch_layer_impl.cc b/chromium/cc/layers/nine_patch_layer_impl.cc
index 103f7656eb8..f609c3d2fda 100644
--- a/chromium/cc/layers/nine_patch_layer_impl.cc
+++ b/chromium/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,120 +50,188 @@ 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);
}
void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
AppendQuadsData* append_quads_data) {
- DCHECK(resource_id_);
-
SharedQuadState* shared_quad_state =
quad_sink->UseSharedQuadState(CreateSharedQuadState());
AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
+ if (!ui_resource_id_)
+ return;
+
+ ResourceProvider::ResourceId resource =
+ layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
+
+ if (!resource)
+ return;
+
static const bool flipped = false;
static const bool premultiplied_alpha = true;
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?
@@ -173,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(),
@@ -186,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(),
@@ -199,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(),
@@ -212,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(),
@@ -225,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(),
@@ -238,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(),
@@ -251,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(),
@@ -264,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(),
@@ -274,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 {
@@ -294,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;
}