1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "nine_patch_layer_impl.h"
7 #include "base/stringprintf.h"
8 #include "cc/quad_sink.h"
9 #include "cc/texture_draw_quad.h"
10 #include "ui/gfx/rect_f.h"
14 NinePatchLayerImpl::NinePatchLayerImpl(int id
)
20 NinePatchLayerImpl::~NinePatchLayerImpl()
24 ResourceProvider::ResourceId
NinePatchLayerImpl::contentsResourceId() const
29 void NinePatchLayerImpl::willDraw(ResourceProvider
* resourceProvider
)
33 static gfx::RectF
normalizedRect(float x
, float y
, float width
, float height
, float totalWidth
, float totalHeight
)
35 return gfx::RectF(x
/ totalWidth
, y
/ totalHeight
, width
/ totalWidth
, height
/ totalHeight
);
38 void NinePatchLayerImpl::setLayout(const gfx::Size
& imageBounds
, const gfx::Rect
& aperture
)
40 m_imageBounds
= imageBounds
;
41 m_imageAperture
= aperture
;
44 void NinePatchLayerImpl::appendQuads(QuadSink
& quadSink
, AppendQuadsData
& appendQuadsData
)
49 SharedQuadState
* sharedQuadState
= quadSink
.useSharedQuadState(createSharedQuadState());
50 appendDebugBorderQuad(quadSink
, sharedQuadState
, appendQuadsData
);
52 static const bool flipped
= false;
53 static const bool premultipliedAlpha
= true;
55 DCHECK(!bounds().IsEmpty());
57 // NinePatch border widths in bitmap pixel space
58 int leftWidth
= m_imageAperture
.x();
59 int topHeight
= m_imageAperture
.y();
60 int rightWidth
= m_imageBounds
.width() - m_imageAperture
.right();
61 int bottomHeight
= m_imageBounds
.height() - m_imageAperture
.bottom();
63 // If layer can't fit the corners, clip to show the outer edges of the
65 int cornerTotalWidth
= leftWidth
+ rightWidth
;
66 int middleWidth
= bounds().width() - cornerTotalWidth
;
67 if (middleWidth
< 0) {
68 float leftWidthProportion
= static_cast<float>(leftWidth
) / cornerTotalWidth
;
69 int leftWidthCrop
= middleWidth
* leftWidthProportion
;
70 leftWidth
+= leftWidthCrop
;
71 rightWidth
= bounds().width() - leftWidth
;
74 int cornerTotalHeight
= topHeight
+ bottomHeight
;
75 int middleHeight
= bounds().height() - cornerTotalHeight
;
76 if (middleHeight
< 0) {
77 float topHeightProportion
= static_cast<float>(topHeight
) / cornerTotalHeight
;
78 int topHeightCrop
= middleHeight
* topHeightProportion
;
79 topHeight
+= topHeightCrop
;
80 bottomHeight
= bounds().height() - topHeight
;
84 // Patch positions in layer space
85 gfx::Rect
topLeft(0, 0, leftWidth
, topHeight
);
86 gfx::Rect
topRight(bounds().width() - rightWidth
, 0, rightWidth
, topHeight
);
87 gfx::Rect
bottomLeft(0, bounds().height() - bottomHeight
, leftWidth
, bottomHeight
);
88 gfx::Rect
bottomRight(topRight
.x(), bottomLeft
.y(), rightWidth
, bottomHeight
);
89 gfx::Rect
top(topLeft
.right(), 0, middleWidth
, topHeight
);
90 gfx::Rect
left(0, topLeft
.bottom(), leftWidth
, middleHeight
);
91 gfx::Rect
right(topRight
.x(), topRight
.bottom(), rightWidth
, left
.height());
92 gfx::Rect
bottom(top
.x(), bottomLeft
.y(), top
.width(), bottomHeight
);
94 float imgWidth
= m_imageBounds
.width();
95 float imgHeight
= m_imageBounds
.height();
97 // Patch positions in bitmap UV space (from zero to one)
98 gfx::RectF uvTopLeft
= normalizedRect(0, 0, leftWidth
, topHeight
, imgWidth
, imgHeight
);
99 gfx::RectF uvTopRight
= normalizedRect(imgWidth
- rightWidth
, 0, rightWidth
, topHeight
, imgWidth
, imgHeight
);
100 gfx::RectF uvBottomLeft
= normalizedRect(0, imgHeight
- bottomHeight
, leftWidth
, bottomHeight
, imgWidth
, imgHeight
);
101 gfx::RectF uvBottomRight
= normalizedRect(imgWidth
- rightWidth
, imgHeight
- bottomHeight
, rightWidth
, bottomHeight
, imgWidth
, imgHeight
);
102 gfx::RectF
uvTop(uvTopLeft
.right(), 0, (imgWidth
- leftWidth
- rightWidth
) / imgWidth
, (topHeight
) / imgHeight
);
103 gfx::RectF
uvLeft(0, uvTopLeft
.bottom(), leftWidth
/ imgWidth
, (imgHeight
- topHeight
- bottomHeight
) / imgHeight
);
104 gfx::RectF
uvRight(uvTopRight
.x(), uvTopRight
.bottom(), rightWidth
/ imgWidth
, uvLeft
.height());
105 gfx::RectF
uvBottom(uvTop
.x(), uvBottomLeft
.y(), uvTop
.width(), bottomHeight
/ imgHeight
);
107 // Nothing is opaque here.
108 // TODO(danakj): Should we look at the SkBitmaps to determine opaqueness?
109 gfx::Rect opaqueRect
;
110 scoped_ptr
<TextureDrawQuad
> quad
;
112 quad
= TextureDrawQuad::Create();
113 quad
->SetNew(sharedQuadState
, topLeft
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvTopLeft
, flipped
);
114 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
116 quad
= TextureDrawQuad::Create();
117 quad
->SetNew(sharedQuadState
, topRight
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvTopRight
, flipped
);
118 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
120 quad
= TextureDrawQuad::Create();
121 quad
->SetNew(sharedQuadState
, bottomLeft
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvBottomLeft
, flipped
);
122 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
124 quad
= TextureDrawQuad::Create();
125 quad
->SetNew(sharedQuadState
, bottomRight
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvBottomRight
, flipped
);
126 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
128 quad
= TextureDrawQuad::Create();
129 quad
->SetNew(sharedQuadState
, top
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvTop
, flipped
);
130 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
132 quad
= TextureDrawQuad::Create();
133 quad
->SetNew(sharedQuadState
, left
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvLeft
, flipped
);
134 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
136 quad
= TextureDrawQuad::Create();
137 quad
->SetNew(sharedQuadState
, right
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvRight
, flipped
);
138 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
140 quad
= TextureDrawQuad::Create();
141 quad
->SetNew(sharedQuadState
, bottom
, opaqueRect
, m_resourceId
, premultipliedAlpha
, uvBottom
, flipped
);
142 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
145 void NinePatchLayerImpl::didDraw(ResourceProvider
* resourceProvider
)
149 void NinePatchLayerImpl::didLoseContext()
154 const char* NinePatchLayerImpl::layerTypeAsString() const
156 return "NinePatchLayer";
159 void NinePatchLayerImpl::dumpLayerProperties(std::string
* str
, int indent
) const
161 str
->append(indentString(indent
));
162 base::StringAppendF(str
, "imageAperture: %s\n", m_imageAperture
.ToString().c_str());
163 LayerImpl::dumpLayerProperties(str
, indent
);