Make castv2 performance test work.
[chromium-blink-merge.git] / ui / views / controls / image_view.cc
blob4025713b6ab6cdd6d3ee2faed051ea11fba74483
1 // Copyright (c) 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 "ui/views/controls/image_view.h"
7 #include "base/logging.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "third_party/skia/include/core/SkPaint.h"
10 #include "ui/accessibility/ax_view_state.h"
11 #include "ui/gfx/canvas.h"
12 #include "ui/gfx/geometry/insets.h"
13 #include "ui/views/painter.h"
15 namespace views {
17 namespace {
19 // Returns the pixels for the bitmap in |image| at scale |image_scale|.
20 void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
21 DCHECK_NE(0.0f, image_scale);
22 const SkBitmap& bitmap = img.GetRepresentation(image_scale).sk_bitmap();
23 SkAutoLockPixels pixel_lock(bitmap);
24 return bitmap.getPixels();
27 } // namespace
29 // static
30 const char ImageView::kViewClassName[] = "ImageView";
32 ImageView::ImageView()
33 : image_size_set_(false),
34 horiz_alignment_(CENTER),
35 vert_alignment_(CENTER),
36 interactive_(true),
37 last_paint_scale_(0.f),
38 last_painted_bitmap_pixels_(NULL),
39 focus_painter_(Painter::CreateDashedFocusPainter()) {
42 ImageView::~ImageView() {
45 void ImageView::SetImage(const gfx::ImageSkia& img) {
46 if (IsImageEqual(img))
47 return;
49 last_painted_bitmap_pixels_ = NULL;
50 gfx::Size pref_size(GetPreferredSize());
51 image_ = img;
52 if (pref_size != GetPreferredSize())
53 PreferredSizeChanged();
54 SchedulePaint();
57 void ImageView::SetImage(const gfx::ImageSkia* image_skia) {
58 if (image_skia) {
59 SetImage(*image_skia);
60 } else {
61 gfx::ImageSkia t;
62 SetImage(t);
66 const gfx::ImageSkia& ImageView::GetImage() {
67 return image_;
70 void ImageView::SetImageSize(const gfx::Size& image_size) {
71 image_size_set_ = true;
72 image_size_ = image_size;
73 PreferredSizeChanged();
76 bool ImageView::GetImageSize(gfx::Size* image_size) const {
77 DCHECK(image_size);
78 if (image_size_set_)
79 *image_size = image_size_;
80 return image_size_set_;
83 gfx::Rect ImageView::GetImageBounds() const {
84 gfx::Size image_size(image_size_set_ ?
85 image_size_ : gfx::Size(image_.width(), image_.height()));
86 return gfx::Rect(ComputeImageOrigin(image_size), image_size);
89 void ImageView::ResetImageSize() {
90 image_size_set_ = false;
93 void ImageView::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
94 focus_painter_ = focus_painter.Pass();
97 gfx::Size ImageView::GetPreferredSize() const {
98 gfx::Insets insets = GetInsets();
99 if (image_size_set_) {
100 gfx::Size image_size;
101 GetImageSize(&image_size);
102 image_size.Enlarge(insets.width(), insets.height());
103 return image_size;
105 return gfx::Size(image_.width() + insets.width(),
106 image_.height() + insets.height());
109 bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
110 // Even though we copy ImageSkia in SetImage() the backing store
111 // (ImageSkiaStorage) is not copied and may have changed since the last call
112 // to SetImage(). The expectation is that SetImage() with different pixels is
113 // treated as though the image changed. For this reason we compare not only
114 // the backing store but also the pixels of the last image we painted.
115 return image_.BackedBySameObjectAs(img) &&
116 last_paint_scale_ != 0.0f &&
117 last_painted_bitmap_pixels_ == GetBitmapPixels(img, last_paint_scale_);
120 gfx::Point ImageView::ComputeImageOrigin(const gfx::Size& image_size) const {
121 gfx::Insets insets = GetInsets();
123 int x;
124 // In order to properly handle alignment of images in RTL locales, we need
125 // to flip the meaning of trailing and leading. For example, if the
126 // horizontal alignment is set to trailing, then we'll use left alignment for
127 // the image instead of right alignment if the UI layout is RTL.
128 Alignment actual_horiz_alignment = horiz_alignment_;
129 if (base::i18n::IsRTL() && (horiz_alignment_ != CENTER))
130 actual_horiz_alignment = (horiz_alignment_ == LEADING) ? TRAILING : LEADING;
131 switch (actual_horiz_alignment) {
132 case LEADING: x = insets.left(); break;
133 case TRAILING: x = width() - insets.right() - image_size.width(); break;
134 case CENTER: x = (width() - image_size.width()) / 2; break;
135 default: NOTREACHED(); x = 0; break;
138 int y;
139 switch (vert_alignment_) {
140 case LEADING: y = insets.top(); break;
141 case TRAILING: y = height() - insets.bottom() - image_size.height(); break;
142 case CENTER: y = (height() - image_size.height()) / 2; break;
143 default: NOTREACHED(); y = 0; break;
146 return gfx::Point(x, y);
149 void ImageView::OnFocus() {
150 View::OnFocus();
151 if (focus_painter_.get())
152 SchedulePaint();
155 void ImageView::OnBlur() {
156 View::OnBlur();
157 if (focus_painter_.get())
158 SchedulePaint();
161 void ImageView::OnPaint(gfx::Canvas* canvas) {
162 View::OnPaint(canvas);
163 OnPaintImage(canvas);
164 Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
167 void ImageView::GetAccessibleState(ui::AXViewState* state) {
168 state->role = ui::AX_ROLE_IMAGE;
169 state->name = tooltip_text_;
172 const char* ImageView::GetClassName() const {
173 return kViewClassName;
176 void ImageView::SetHorizontalAlignment(Alignment ha) {
177 if (ha != horiz_alignment_) {
178 horiz_alignment_ = ha;
179 SchedulePaint();
183 ImageView::Alignment ImageView::GetHorizontalAlignment() const {
184 return horiz_alignment_;
187 void ImageView::SetVerticalAlignment(Alignment va) {
188 if (va != vert_alignment_) {
189 vert_alignment_ = va;
190 SchedulePaint();
194 ImageView::Alignment ImageView::GetVerticalAlignment() const {
195 return vert_alignment_;
198 void ImageView::SetTooltipText(const base::string16& tooltip) {
199 tooltip_text_ = tooltip;
202 base::string16 ImageView::GetTooltipText() const {
203 return tooltip_text_;
206 bool ImageView::GetTooltipText(const gfx::Point& p,
207 base::string16* tooltip) const {
208 if (tooltip_text_.empty())
209 return false;
211 *tooltip = GetTooltipText();
212 return true;
215 bool ImageView::CanProcessEventsWithinSubtree() const {
216 return interactive_;
219 void ImageView::OnPaintImage(gfx::Canvas* canvas) {
220 last_paint_scale_ = canvas->image_scale();
221 last_painted_bitmap_pixels_ = NULL;
223 if (image_.isNull())
224 return;
226 gfx::Rect image_bounds(GetImageBounds());
227 if (image_bounds.IsEmpty())
228 return;
230 if (image_bounds.size() != gfx::Size(image_.width(), image_.height())) {
231 // Resize case
232 SkPaint paint;
233 paint.setFilterQuality(kLow_SkFilterQuality);
234 canvas->DrawImageInt(image_, 0, 0, image_.width(), image_.height(),
235 image_bounds.x(), image_bounds.y(), image_bounds.width(),
236 image_bounds.height(), true, paint);
237 } else {
238 canvas->DrawImageInt(image_, image_bounds.x(), image_bounds.y());
240 last_painted_bitmap_pixels_ = GetBitmapPixels(image_, last_paint_scale_);
243 } // namespace views