Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: ui/views/bubble/bubble_border.cc

Issue 10905311: Consolidate bubble border code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: for comments in #3 Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/bubble/bubble_border.h" 5 #include "ui/views/bubble/bubble_border.h"
6 6
7 #include <algorithm> // for std::max 7 #include <algorithm> // for std::max
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "grit/ui_resources.h" 10 #include "grit/ui_resources.h"
11 #include "ui/base/resource/resource_bundle.h" 11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/image/image_skia.h" 13 #include "ui/gfx/image/image_skia.h"
14 #include "ui/gfx/skia_util.h" 14 #include "ui/gfx/skia_util.h"
15 15
16 namespace {
17
18 // Stroke size in pixels of borders in image assets.
19 const int kBorderStrokeSize = 1;
20
21 // Border image resource ids.
22 const int kShadowImages[] = {
23 IDR_BUBBLE_SHADOW_L,
24 IDR_BUBBLE_SHADOW_TL,
25 IDR_BUBBLE_SHADOW_T,
26 IDR_BUBBLE_SHADOW_TR,
27 IDR_BUBBLE_SHADOW_R,
28 IDR_BUBBLE_SHADOW_BR,
29 IDR_BUBBLE_SHADOW_B,
30 IDR_BUBBLE_SHADOW_BL,
31 };
32
33 const int kNoShadowImages[] = {
34 IDR_BUBBLE_L,
35 IDR_BUBBLE_TL,
36 IDR_BUBBLE_T,
37 IDR_BUBBLE_TR,
38 IDR_BUBBLE_R,
39 IDR_BUBBLE_BR,
40 IDR_BUBBLE_B,
41 IDR_BUBBLE_BL,
42 IDR_BUBBLE_L_ARROW,
43 IDR_BUBBLE_T_ARROW,
44 IDR_BUBBLE_R_ARROW,
45 IDR_BUBBLE_B_ARROW,
46 };
47
48 #if defined(USE_AURA)
49 const int kBigShadowImages[] = {
50 IDR_WINDOW_BUBBLE_SHADOW_BIG_LEFT,
51 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_LEFT,
52 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP,
53 IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_RIGHT,
54 IDR_WINDOW_BUBBLE_SHADOW_BIG_RIGHT,
55 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_RIGHT,
56 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM,
57 IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_LEFT,
58 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_LEFT,
59 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_TOP,
60 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_RIGHT,
61 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_BOTTOM,
62 };
63
64 const int kSmallShadowImages[] = {
65 IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT,
66 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT,
67 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP,
68 IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT,
69 IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT,
70 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT,
71 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM,
72 IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT,
73 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_LEFT,
74 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_TOP,
75 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_RIGHT,
76 IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_BOTTOM,
77 };
78 #endif
79
80 } // namespace
81
16 namespace views { 82 namespace views {
17 83
18 struct BubbleBorder::BorderImages { 84 struct BubbleBorder::BorderImages {
19 BorderImages() 85 BorderImages(const int image_ids[],
20 : left(NULL), 86 size_t image_ids_size,
21 top_left(NULL), 87 int arrow_interior_height,
22 top(NULL), 88 int border_thickness,
23 top_right(NULL), 89 int corner_radius)
24 right(NULL), 90 : arrow_interior_height(arrow_interior_height),
25 bottom_right(NULL), 91 border_thickness(border_thickness),
26 bottom(NULL), 92 corner_radius(corner_radius) {
27 bottom_left(NULL), 93 // Only two possible sizes of image ids array.
28 left_arrow(NULL), 94 DCHECK(image_ids_size == 12 || image_ids_size == 8);
29 top_arrow(NULL), 95
30 right_arrow(NULL), 96 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
31 bottom_arrow(NULL), 97
32 border_thickness(0) { 98 left = *rb.GetImageNamed(image_ids[0]).ToImageSkia();
99 top_left = *rb.GetImageNamed(image_ids[1]).ToImageSkia();
100 top = *rb.GetImageNamed(image_ids[2]).ToImageSkia();
101 top_right = *rb.GetImageNamed(image_ids[3]).ToImageSkia();
102 right = *rb.GetImageNamed(image_ids[4]).ToImageSkia();
103 bottom_right = *rb.GetImageNamed(image_ids[5]).ToImageSkia();
104 bottom = *rb.GetImageNamed(image_ids[6]).ToImageSkia();
105 bottom_left = *rb.GetImageNamed(image_ids[7]).ToImageSkia();
106
107 if (image_ids_size > 8) {
108 left_arrow = *rb.GetImageNamed(image_ids[8]).ToImageSkia();
109 top_arrow = *rb.GetImageNamed(image_ids[9]).ToImageSkia();
110 right_arrow = *rb.GetImageNamed(image_ids[10]).ToImageSkia();
111 bottom_arrow = *rb.GetImageNamed(image_ids[11]).ToImageSkia();
112 }
33 } 113 }
34 114
35 gfx::ImageSkia* left; 115 gfx::ImageSkia left;
36 gfx::ImageSkia* top_left; 116 gfx::ImageSkia top_left;
37 gfx::ImageSkia* top; 117 gfx::ImageSkia top;
38 gfx::ImageSkia* top_right; 118 gfx::ImageSkia top_right;
39 gfx::ImageSkia* right; 119 gfx::ImageSkia right;
40 gfx::ImageSkia* bottom_right; 120 gfx::ImageSkia bottom_right;
41 gfx::ImageSkia* bottom; 121 gfx::ImageSkia bottom;
42 gfx::ImageSkia* bottom_left; 122 gfx::ImageSkia bottom_left;
43 gfx::ImageSkia* left_arrow; 123
44 gfx::ImageSkia* top_arrow; 124 gfx::ImageSkia left_arrow;
45 gfx::ImageSkia* right_arrow; 125 gfx::ImageSkia top_arrow;
46 gfx::ImageSkia* bottom_arrow; 126 gfx::ImageSkia right_arrow;
127 gfx::ImageSkia bottom_arrow;
128
129 int arrow_interior_height; // The height inside the arrow image, in pixels.
47 int border_thickness; 130 int border_thickness;
131 int corner_radius;
48 }; 132 };
49 133
50 // static 134 // static
51 struct BubbleBorder::BorderImages* BubbleBorder::normal_images_ = NULL; 135 struct BubbleBorder::BorderImages*
52 struct BubbleBorder::BorderImages* BubbleBorder::shadow_images_ = NULL; 136 BubbleBorder::border_images_[SHADOW_COUNT] = { NULL };
msw 2012/09/19 20:12:32 nit: indent by 4 spaces.
xiyuan 2012/09/19 22:51:36 Done.
53
54 // The height inside the arrow image, in pixels.
55 static const int kArrowInteriorHeight = 7;
56 137
57 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow) 138 BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow)
58 : override_arrow_offset_(0), 139 : override_arrow_offset_(0),
59 arrow_location_(arrow_location), 140 arrow_location_(arrow_location),
60 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), 141 alignment_(ALIGN_ARROW_TO_MID_ANCHOR),
61 background_color_(SK_ColorWHITE) { 142 background_color_(SK_ColorWHITE) {
143 DCHECK(shadow < SHADOW_COUNT);
62 images_ = GetBorderImages(shadow); 144 images_ = GetBorderImages(shadow);
63 145
64 // Calculate horizontal and vertical insets for arrow by ensuring that 146 // Calculate horizontal and vertical insets for arrow by ensuring that
65 // the widest arrow and corner images will have enough room to avoid overlap 147 // the widest arrow and corner images will have enough room to avoid overlap
66 int offset_x = 148 int offset_x =
67 (std::max(images_->top_arrow->width(), 149 (std::max(images_->top_arrow.width(),
68 images_->bottom_arrow->width()) / 2) + 150 images_->bottom_arrow.width()) / 2) +
69 std::max(std::max(images_->top_left->width(), 151 std::max(std::max(images_->top_left.width(),
70 images_->top_right->width()), 152 images_->top_right.width()),
71 std::max(images_->bottom_left->width(), 153 std::max(images_->bottom_left.width(),
72 images_->bottom_right->width())); 154 images_->bottom_right.width()));
73 int offset_y = 155 int offset_y =
74 (std::max(images_->left_arrow->height(), 156 (std::max(images_->left_arrow.height(),
75 images_->right_arrow->height()) / 2) + 157 images_->right_arrow.height()) / 2) +
76 std::max(std::max(images_->top_left->height(), 158 std::max(std::max(images_->top_left.height(),
77 images_->top_right->height()), 159 images_->top_right.height()),
78 std::max(images_->bottom_left->height(), 160 std::max(images_->bottom_left.height(),
79 images_->bottom_right->height())); 161 images_->bottom_right.height()));
80 arrow_offset_ = std::max(offset_x, offset_y); 162 arrow_offset_ = std::max(offset_x, offset_y);
81 } 163 }
82 164
83 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, 165 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
84 const gfx::Size& contents_size) const { 166 const gfx::Size& contents_size) const {
85 // Desired size is size of contents enlarged by the size of the border images. 167 // Desired size is size of contents enlarged by the size of the border images.
86 gfx::Size border_size(contents_size); 168 gfx::Size border_size(contents_size);
87 gfx::Insets insets; 169 gfx::Insets insets;
88 GetInsets(&insets); 170 GetInsets(&insets);
89 border_size.Enlarge(insets.width(), insets.height()); 171 border_size.Enlarge(insets.width(), insets.height());
90 172
91 // Ensure the bubble has a minimum size that draws arrows correctly. 173 // Ensure the bubble has a minimum size that draws arrows correctly.
92 if (is_arrow_on_horizontal(arrow_location_)) 174 if (is_arrow_on_horizontal(arrow_location_))
93 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_)); 175 border_size.set_width(std::max(border_size.width(), 2 * arrow_offset_));
94 else if (has_arrow(arrow_location_)) 176 else if (has_arrow(arrow_location_))
95 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_)); 177 border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_));
96 178
97 // Screen position depends on the arrow location. 179 // Screen position depends on the arrow location.
98 // The arrow should overlap the target by some amount since there is space 180 // The bubble should overlap the target by some amount since there is space
99 // for shadow between arrow tip and image bounds. 181 // for shadow between arrow tip/bubble border and image bounds.
100 const int kArrowOverlap = 3;
101 int x = position_relative_to.x(); 182 int x = position_relative_to.x();
102 int y = position_relative_to.y(); 183 int y = position_relative_to.y();
103 int w = position_relative_to.width(); 184 int w = position_relative_to.width();
104 int h = position_relative_to.height(); 185 int h = position_relative_to.height();
105 int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : 186
106 arrow_offset_; 187 const int arrow_size = images_->arrow_interior_height + kBorderStrokeSize;
188 const int arrow_offset = GetArrowOffset(border_size);
107 189
108 // Calculate bubble x coordinate. 190 // Calculate bubble x coordinate.
109 switch (arrow_location_) { 191 switch (arrow_location_) {
110 case TOP_LEFT: 192 case TOP_LEFT:
111 case BOTTOM_LEFT: 193 case BOTTOM_LEFT:
112 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset : 194 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset :
113 -kArrowOverlap; 195 -(images_->left.width() - kBorderStrokeSize);
114 break; 196 break;
115 197
116 case TOP_RIGHT: 198 case TOP_RIGHT:
117 case BOTTOM_RIGHT: 199 case BOTTOM_RIGHT:
118 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 200 x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
119 w / 2 + arrow_offset - border_size.width() + 1 : 201 w / 2 + arrow_offset - border_size.width() + 1 :
120 w - border_size.width() + kArrowOverlap; 202 w - border_size.width() + images_->right.width() - kBorderStrokeSize;
121 break; 203 break;
122 204
123 case LEFT_TOP: 205 case LEFT_TOP:
206 case LEFT_CENTER:
124 case LEFT_BOTTOM: 207 case LEFT_BOTTOM:
125 x += w - kArrowOverlap; 208 x += w - (images_->left_arrow.width() - arrow_size);
126 break; 209 break;
127 210
128 case RIGHT_TOP: 211 case RIGHT_TOP:
212 case RIGHT_CENTER:
129 case RIGHT_BOTTOM: 213 case RIGHT_BOTTOM:
130 x += kArrowOverlap - border_size.width(); 214 x += images_->right_arrow.width() - arrow_size - border_size.width();
215 break;
216
217 case TOP_CENTER:
218 case BOTTOM_CENTER:
219 x += w / 2 - arrow_offset;
131 break; 220 break;
132 221
133 case NONE: 222 case NONE:
134 case FLOAT: 223 case FLOAT:
135 x += w / 2 - border_size.width() / 2; 224 x += w / 2 - border_size.width() / 2;
136 break; 225 break;
137 } 226 }
138 227
139 // Calculate bubble y coordinate. 228 // Calculate bubble y coordinate.
140 switch (arrow_location_) { 229 switch (arrow_location_) {
141 case TOP_LEFT: 230 case TOP_LEFT:
231 case TOP_CENTER:
142 case TOP_RIGHT: 232 case TOP_RIGHT:
143 y += h - kArrowOverlap; 233 y += h - (images_->top_arrow.height() - arrow_size);
144 break; 234 break;
145 235
146 case BOTTOM_LEFT: 236 case BOTTOM_LEFT:
237 case BOTTOM_CENTER:
147 case BOTTOM_RIGHT: 238 case BOTTOM_RIGHT:
148 y += kArrowOverlap - border_size.height(); 239 y += images_->bottom_arrow.height() - arrow_size -
240 border_size.height();
149 break; 241 break;
150 242
151 case LEFT_TOP: 243 case LEFT_TOP:
152 case RIGHT_TOP: 244 case RIGHT_TOP:
153 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset : 245 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset :
154 -kArrowOverlap; 246 -(images_->top.height() - kBorderStrokeSize);
155 break; 247 break;
156 248
157 case LEFT_BOTTOM: 249 case LEFT_BOTTOM:
158 case RIGHT_BOTTOM: 250 case RIGHT_BOTTOM:
159 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? 251 y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ?
160 h / 2 + arrow_offset - border_size.height() + 1 : 252 h / 2 + arrow_offset - border_size.height() + 1 :
161 h - border_size.height() + kArrowOverlap; 253 h - border_size.height() + images_->bottom.height() -
254 kBorderStrokeSize;
msw 2012/09/19 20:12:32 nit: indent four more spaces.
xiyuan 2012/09/19 22:51:36 Done.
255 break;
256
257 case LEFT_CENTER:
258 case RIGHT_CENTER:
259 y += h / 2 - arrow_offset;
162 break; 260 break;
163 261
164 case NONE: 262 case NONE:
165 y += h; 263 y += h;
166 break; 264 break;
167 265
168 case FLOAT: 266 case FLOAT:
169 y += h / 2 - border_size.height() / 2; 267 y += h / 2 - border_size.height() / 2;
170 break; 268 break;
171 } 269 }
172 270
173 return gfx::Rect(x, y, border_size.width(), border_size.height()); 271 return gfx::Rect(x, y, border_size.width(), border_size.height());
174 } 272 }
175 273
176 void BubbleBorder::GetInsets(gfx::Insets* insets) const { 274 void BubbleBorder::GetInsets(gfx::Insets* insets) const {
177 return GetInsetsForArrowLocation(insets, arrow_location()); 275 return GetInsetsForArrowLocation(insets, arrow_location());
178 } 276 }
179 277
180 void BubbleBorder::GetInsetsForArrowLocation(gfx::Insets* insets, 278 void BubbleBorder::GetInsetsForArrowLocation(gfx::Insets* insets,
181 ArrowLocation arrow_loc) const { 279 ArrowLocation arrow_loc) const {
182 int top = images_->top->height(); 280 int top = images_->top.height();
183 int bottom = images_->bottom->height(); 281 int bottom = images_->bottom.height();
184 int left = images_->left->width(); 282 int left = images_->left.width();
185 int right = images_->right->width(); 283 int right = images_->right.width();
186 switch (arrow_loc) { 284 switch (arrow_loc) {
187 case TOP_LEFT: 285 case TOP_LEFT:
286 case TOP_CENTER:
188 case TOP_RIGHT: 287 case TOP_RIGHT:
189 top = std::max(top, images_->top_arrow->height()); 288 top = std::max(top, images_->top_arrow.height());
190 break; 289 break;
191 290
192 case BOTTOM_LEFT: 291 case BOTTOM_LEFT:
292 case BOTTOM_CENTER:
193 case BOTTOM_RIGHT: 293 case BOTTOM_RIGHT:
194 bottom = std::max(bottom, images_->bottom_arrow->height()); 294 bottom = std::max(bottom, images_->bottom_arrow.height());
195 break; 295 break;
196 296
197 case LEFT_TOP: 297 case LEFT_TOP:
298 case LEFT_CENTER:
198 case LEFT_BOTTOM: 299 case LEFT_BOTTOM:
199 left = std::max(left, images_->left_arrow->width()); 300 left = std::max(left, images_->left_arrow.width());
200 break; 301 break;
201 302
202 case RIGHT_TOP: 303 case RIGHT_TOP:
304 case RIGHT_CENTER:
203 case RIGHT_BOTTOM: 305 case RIGHT_BOTTOM:
204 right = std::max(right, images_->right_arrow->width()); 306 right = std::max(right, images_->right_arrow.width());
205 break; 307 break;
206 308
207 case NONE: 309 case NONE:
208 case FLOAT: 310 case FLOAT:
209 // Nothing to do. 311 // Nothing to do.
210 break; 312 break;
211 } 313 }
212 insets->Set(top, left, bottom, right); 314 insets->Set(top, left, bottom, right);
213 } 315 }
214 316
215 int BubbleBorder::GetBorderThickness() const { 317 int BubbleBorder::GetBorderThickness() const {
216 return images_->border_thickness; 318 return images_->border_thickness;
217 } 319 }
218 320
219 int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { 321 int BubbleBorder::GetBorderCornerRadius() const {
220 gfx::Size border_size(contents_size); 322 return images_->corner_radius;
221 gfx::Insets insets; 323 }
222 GetInsets(&insets); 324
223 border_size.Enlarge(insets.left() + insets.right(), 325 int BubbleBorder::GetArrowOffset(const gfx::Size& border_size) const {
224 insets.top() + insets.bottom()); 326 int arrow_offset = arrow_offset_;
225 offset = std::max(arrow_offset_, 327 if (override_arrow_offset_) {
226 std::min(offset, (is_arrow_on_horizontal(arrow_location_) ? 328 arrow_offset = override_arrow_offset_;
227 border_size.width() : border_size.height()) - arrow_offset_)); 329 } else if (is_arrow_at_center(arrow_location_)) {
228 override_arrow_offset_ = offset; 330 if (is_arrow_on_horizontal(arrow_location_))
229 return override_arrow_offset_; 331 arrow_offset = border_size.width() / 2;
332 else
333 arrow_offset = border_size.height() / 2;
334 }
335
336 return std::max(arrow_offset_,
msw 2012/09/19 20:12:32 nit: add a comment on what clamping/validation thi
xiyuan 2012/09/19 22:51:36 Done.
337 std::min(arrow_offset, (is_arrow_on_horizontal(arrow_location_) ?
338 border_size.width() - arrow_offset_:
msw 2012/09/19 20:12:32 nit: space before colon.
xiyuan 2012/09/19 22:51:36 I changed the expression in the wrong way (did not
339 border_size.height()) - arrow_offset_));
230 } 340 }
231 341
232 // static 342 // static
233 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) { 343 BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) {
234 if (shadow == SHADOW && shadow_images_ == NULL) { 344 CHECK(shadow < SHADOW_COUNT);
msw 2012/09/19 20:12:32 nit: CHECK_LT
xiyuan 2012/09/19 22:51:36 Done.
235 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 345
236 shadow_images_ = new BorderImages(); 346 struct BorderImages*& images = border_images_[shadow];
237 shadow_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_L); 347 if (images)
238 shadow_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TL); 348 return images;
239 shadow_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_T); 349
240 shadow_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TR); 350 switch (shadow) {
241 shadow_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_R); 351 case SHADOW:
242 shadow_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BR); 352 images = new BorderImages(kShadowImages,
243 shadow_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_B); 353 arraysize(kShadowImages),
244 shadow_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BL); 354 0, 10, 4);
245 shadow_images_->left_arrow = new gfx::ImageSkia(); 355 break;
246 shadow_images_->top_arrow = new gfx::ImageSkia(); 356 case NO_SHADOW:
247 shadow_images_->right_arrow = new gfx::ImageSkia(); 357 images = new BorderImages(kNoShadowImages,
248 shadow_images_->bottom_arrow = new gfx::ImageSkia(); 358 arraysize(kNoShadowImages),
249 shadow_images_->border_thickness = 10; 359 7, 0, 4);
250 } else if (shadow == NO_SHADOW && normal_images_ == NULL) { 360 break;
251 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 361 #if defined(USE_AURA)
252 normal_images_ = new BorderImages(); 362 case BIG_SHADOW:
253 normal_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_L); 363 images = new BorderImages(kBigShadowImages,
254 normal_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_TL); 364 arraysize(kBigShadowImages),
255 normal_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_T); 365 9, 0, 3);
256 normal_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_TR); 366 break;
257 normal_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_R); 367 case SMALL_SHADOW:
258 normal_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_BR); 368 images = new BorderImages(kSmallShadowImages,
259 normal_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_B); 369 arraysize(kSmallShadowImages),
260 normal_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_BL); 370 9, 0, 3);
261 normal_images_->left_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_L_ARROW); 371 break;
262 normal_images_->top_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_T_ARROW); 372 #endif
263 normal_images_->right_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_R_ARROW); 373 default:
264 normal_images_->bottom_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_B_ARROW); 374 NOTREACHED();
265 normal_images_->border_thickness = 0; 375 break;
266 } 376 }
267 return shadow == SHADOW ? shadow_images_ : normal_images_; 377
378 return images;
268 } 379 }
269 380
270 BubbleBorder::~BubbleBorder() {} 381 BubbleBorder::~BubbleBorder() {}
271 382
272 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { 383 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
273 // Convenience shorthand variables. 384 // Convenience shorthand variables.
274 const int tl_width = images_->top_left->width(); 385 const int tl_width = images_->top_left.width();
275 const int tl_height = images_->top_left->height(); 386 const int tl_height = images_->top_left.height();
276 const int t_height = images_->top->height(); 387 const int t_height = images_->top.height();
277 const int tr_width = images_->top_right->width(); 388 const int tr_width = images_->top_right.width();
278 const int tr_height = images_->top_right->height(); 389 const int tr_height = images_->top_right.height();
279 const int l_width = images_->left->width(); 390 const int l_width = images_->left.width();
280 const int r_width = images_->right->width(); 391 const int r_width = images_->right.width();
281 const int br_width = images_->bottom_right->width(); 392 const int br_width = images_->bottom_right.width();
282 const int br_height = images_->bottom_right->height(); 393 const int br_height = images_->bottom_right.height();
283 const int b_height = images_->bottom->height(); 394 const int b_height = images_->bottom.height();
284 const int bl_width = images_->bottom_left->width(); 395 const int bl_width = images_->bottom_left.width();
285 const int bl_height = images_->bottom_left->height(); 396 const int bl_height = images_->bottom_left.height();
286 397
287 gfx::Insets insets; 398 gfx::Insets insets;
288 GetInsets(&insets); 399 GetInsets(&insets);
289 const int top = insets.top() - t_height; 400 const int top = insets.top() - t_height;
290 const int bottom = view.height() - insets.bottom() + b_height; 401 const int bottom = view.height() - insets.bottom() + b_height;
291 const int left = insets.left() - l_width; 402 const int left = insets.left() - l_width;
292 const int right = view.width() - insets.right() + r_width; 403 const int right = view.width() - insets.right() + r_width;
293 const int height = bottom - top; 404 const int height = bottom - top;
294 const int width = right - left; 405 const int width = right - left;
295 406
296 // |arrow_offset| is offset of arrow from the begining of the edge. 407 // |arrow_offset| is offset of arrow from the beginning of the edge.
297 int arrow_offset = arrow_offset_; 408 int arrow_offset = GetArrowOffset(view.size());
298 if (override_arrow_offset_) 409 if (is_arrow_on_horizontal(arrow_location_) &&
299 arrow_offset = override_arrow_offset_; 410 !is_arrow_on_left(arrow_location_)) {
300 else if (is_arrow_on_horizontal(arrow_location_) &&
301 !is_arrow_on_left(arrow_location_)) {
302 arrow_offset = view.width() - arrow_offset - 1; 411 arrow_offset = view.width() - arrow_offset - 1;
303 } else if (!is_arrow_on_horizontal(arrow_location_) && 412 } else if (!is_arrow_on_horizontal(arrow_location_) &&
304 !is_arrow_on_top(arrow_location_)) { 413 !is_arrow_on_top(arrow_location_)) {
305 arrow_offset = view.height() - arrow_offset - 1; 414 arrow_offset = view.height() - arrow_offset - 1;
306 } 415 }
307 416
308 // Left edge. 417 // Left edge.
309 if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { 418 if (arrow_location_ == LEFT_TOP ||
419 arrow_location_ == LEFT_CENTER ||
420 arrow_location_ == LEFT_BOTTOM) {
310 int start_y = top + tl_height; 421 int start_y = top + tl_height;
311 int before_arrow = 422 int before_arrow =
312 arrow_offset - start_y - images_->left_arrow->height() / 2; 423 arrow_offset - start_y - images_->left_arrow.height() / 2;
313 int after_arrow = height - tl_height - bl_height - 424 int after_arrow = height - tl_height - bl_height -
314 images_->left_arrow->height() - before_arrow; 425 images_->left_arrow.height() - before_arrow;
315 // Shift tip coordinates half pixel so that skia draws the tip correctly. 426 // Shift tip coordinates half pixel so that skia draws the tip correctly.
316 DrawArrowInterior(canvas, 427 DrawArrowInterior(canvas,
317 images_->left_arrow->width() - kArrowInteriorHeight - 0.5f, 428 images_->left_arrow.width() - images_->arrow_interior_height - 0.5f,
318 start_y + before_arrow + images_->left_arrow->height() / 2 - 0.5f); 429 start_y + before_arrow + images_->left_arrow.height() / 2 - 0.5f);
319 DrawEdgeWithArrow(canvas, 430 DrawEdgeWithArrow(canvas,
320 false, 431 false,
321 images_->left, 432 images_->left,
322 images_->left_arrow, 433 images_->left_arrow,
323 left, 434 left,
324 start_y, 435 start_y,
325 before_arrow, 436 before_arrow,
326 after_arrow, 437 after_arrow,
327 images_->left->width() - images_->left_arrow->width()); 438 images_->left.width() - images_->left_arrow.width());
328 } else { 439 } else {
329 canvas->TileImageInt(*images_->left, left, top + tl_height, l_width, 440 canvas->TileImageInt(images_->left, left, top + tl_height, l_width,
330 height - tl_height - bl_height); 441 height - tl_height - bl_height);
331 } 442 }
332 443
333 // Top left corner. 444 // Top left corner.
334 canvas->DrawImageInt(*images_->top_left, left, top); 445 canvas->DrawImageInt(images_->top_left, left, top);
335 446
336 // Top edge. 447 // Top edge.
337 if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { 448 if (arrow_location_ == TOP_LEFT ||
449 arrow_location_ == TOP_CENTER ||
450 arrow_location_ == TOP_RIGHT) {
338 int start_x = left + tl_width; 451 int start_x = left + tl_width;
339 int before_arrow = arrow_offset - start_x - images_->top_arrow->width() / 2; 452 int before_arrow = arrow_offset - start_x - images_->top_arrow.width() / 2;
340 int after_arrow = width - tl_width - tr_width - 453 int after_arrow = width - tl_width - tr_width -
341 images_->top_arrow->width() - before_arrow; 454 images_->top_arrow.width() - before_arrow;
342 DrawArrowInterior(canvas, 455 DrawArrowInterior(canvas,
343 start_x + before_arrow + images_->top_arrow->width() / 2, 456 start_x + before_arrow + images_->top_arrow.width() / 2,
344 images_->top_arrow->height() - kArrowInteriorHeight); 457 images_->top_arrow.height() - images_->arrow_interior_height);
345 DrawEdgeWithArrow(canvas, 458 DrawEdgeWithArrow(canvas,
346 true, 459 true,
347 images_->top, 460 images_->top,
348 images_->top_arrow, 461 images_->top_arrow,
349 start_x, 462 start_x,
350 top, 463 top,
351 before_arrow, 464 before_arrow,
352 after_arrow, 465 after_arrow,
353 images_->top->height() - images_->top_arrow->height()); 466 images_->top.height() - images_->top_arrow.height());
354 } else { 467 } else {
355 canvas->TileImageInt(*images_->top, left + tl_width, top, 468 canvas->TileImageInt(images_->top, left + tl_width, top,
356 width - tl_width - tr_width, t_height); 469 width - tl_width - tr_width, t_height);
357 } 470 }
358 471
359 // Top right corner. 472 // Top right corner.
360 canvas->DrawImageInt(*images_->top_right, right - tr_width, top); 473 canvas->DrawImageInt(images_->top_right, right - tr_width, top);
361 474
362 // Right edge. 475 // Right edge.
363 if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { 476 if (arrow_location_ == RIGHT_TOP ||
477 arrow_location_ == RIGHT_CENTER ||
478 arrow_location_ == RIGHT_BOTTOM) {
364 int start_y = top + tr_height; 479 int start_y = top + tr_height;
365 int before_arrow = 480 int before_arrow =
366 arrow_offset - start_y - images_->right_arrow->height() / 2; 481 arrow_offset - start_y - images_->right_arrow.height() / 2;
367 int after_arrow = height - tl_height - bl_height - 482 int after_arrow = height - tl_height - bl_height -
368 images_->right_arrow->height() - before_arrow; 483 images_->right_arrow.height() - before_arrow;
369 // Shift tip coordinates half pixel so that skia draws the tip correctly. 484 // Shift tip coordinates half pixel so that skia draws the tip correctly.
370 DrawArrowInterior(canvas, 485 DrawArrowInterior(canvas,
371 right - r_width + kArrowInteriorHeight - 0.5f, 486 right - r_width + images_->arrow_interior_height - 0.5f,
372 start_y + before_arrow + images_->right_arrow->height() / 2 - 0.5f); 487 start_y + before_arrow + images_->right_arrow.height() / 2 - 0.5f);
373 DrawEdgeWithArrow(canvas, 488 DrawEdgeWithArrow(canvas,
374 false, 489 false,
375 images_->right, 490 images_->right,
376 images_->right_arrow, 491 images_->right_arrow,
377 right - r_width, 492 right - r_width,
378 start_y, 493 start_y,
379 before_arrow, 494 before_arrow,
380 after_arrow, 495 after_arrow,
381 0); 496 0);
382 } else { 497 } else {
383 canvas->TileImageInt(*images_->right, right - r_width, top + tr_height, 498 canvas->TileImageInt(images_->right, right - r_width, top + tr_height,
384 r_width, height - tr_height - br_height); 499 r_width, height - tr_height - br_height);
385 } 500 }
386 501
387 // Bottom right corner. 502 // Bottom right corner.
388 canvas->DrawImageInt(*images_->bottom_right, 503 canvas->DrawImageInt(images_->bottom_right,
389 right - br_width, 504 right - br_width,
390 bottom - br_height); 505 bottom - br_height);
391 506
392 // Bottom edge. 507 // Bottom edge.
393 if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { 508 if (arrow_location_ == BOTTOM_LEFT ||
509 arrow_location_ == BOTTOM_CENTER ||
510 arrow_location_ == BOTTOM_RIGHT) {
394 int start_x = left + bl_width; 511 int start_x = left + bl_width;
395 int before_arrow = 512 int before_arrow =
396 arrow_offset - start_x - images_->bottom_arrow->width() / 2; 513 arrow_offset - start_x - images_->bottom_arrow.width() / 2;
397 int after_arrow = width - bl_width - br_width - 514 int after_arrow = width - bl_width - br_width -
398 images_->bottom_arrow->width() - before_arrow; 515 images_->bottom_arrow.width() - before_arrow;
399 DrawArrowInterior(canvas, 516 DrawArrowInterior(canvas,
400 start_x + before_arrow + images_->bottom_arrow->width() / 2, 517 start_x + before_arrow + images_->bottom_arrow.width() / 2,
401 bottom - b_height + kArrowInteriorHeight); 518 bottom - b_height + images_->arrow_interior_height);
402 DrawEdgeWithArrow(canvas, 519 DrawEdgeWithArrow(canvas,
403 true, 520 true,
404 images_->bottom, 521 images_->bottom,
405 images_->bottom_arrow, 522 images_->bottom_arrow,
406 start_x, 523 start_x,
407 bottom - b_height, 524 bottom - b_height,
408 before_arrow, 525 before_arrow,
409 after_arrow, 526 after_arrow,
410 0); 527 0);
411 } else { 528 } else {
412 canvas->TileImageInt(*images_->bottom, left + bl_width, bottom - b_height, 529 canvas->TileImageInt(images_->bottom, left + bl_width, bottom - b_height,
413 width - bl_width - br_width, b_height); 530 width - bl_width - br_width, b_height);
414 } 531 }
415 532
416 // Bottom left corner. 533 // Bottom left corner.
417 canvas->DrawImageInt(*images_->bottom_left, left, bottom - bl_height); 534 canvas->DrawImageInt(images_->bottom_left, left, bottom - bl_height);
418 } 535 }
419 536
420 void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas, 537 void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas,
421 bool is_horizontal, 538 bool is_horizontal,
422 gfx::ImageSkia* edge, 539 const gfx::ImageSkia& edge,
423 gfx::ImageSkia* arrow, 540 const gfx::ImageSkia& arrow,
424 int start_x, 541 int start_x,
425 int start_y, 542 int start_y,
426 int before_arrow, 543 int before_arrow,
427 int after_arrow, 544 int after_arrow,
428 int offset) const { 545 int offset) const {
429 /* Here's what the parameters mean: 546 /* Here's what the parameters mean:
430 * start_x 547 * start_x
431 * . 548 * .
432 * . ┌───┐ ┬ offset 549 * . ┌───┐ ┬ offset
433 * start_y..........┌────┬────────┤ ▲ ├────────┬────┐ 550 * start_y..........┌────┬────────┤ ▲ ├────────┬────┐
434 * │ / │--------│∙ ∙│--------│ \ │ 551 * │ / │--------│∙ ∙│--------│ \ │
435 * │ / ├────────┴───┴────────┤ \ │ 552 * │ / ├────────┴───┴────────┤ \ │
436 * ├───┬┘ └┬───┤ 553 * ├───┬┘ └┬───┤
437 * └───┬────┘ └───┬────┘ 554 * └───┬────┘ └───┬────┘
438 * before_arrow ─┘ └─ after_arrow 555 * before_arrow ─┘ └─ after_arrow
439 */ 556 */
440 if (before_arrow) { 557 if (before_arrow) {
441 canvas->TileImageInt(*edge, start_x, start_y, 558 canvas->TileImageInt(edge, start_x, start_y,
442 is_horizontal ? before_arrow : edge->width(), 559 is_horizontal ? before_arrow : edge.width(),
443 is_horizontal ? edge->height() : before_arrow); 560 is_horizontal ? edge.height() : before_arrow);
444 } 561 }
445 562
446 canvas->DrawImageInt(*arrow, 563 canvas->DrawImageInt(arrow,
447 start_x + (is_horizontal ? before_arrow : offset), 564 start_x + (is_horizontal ? before_arrow : offset),
448 start_y + (is_horizontal ? offset : before_arrow)); 565 start_y + (is_horizontal ? offset : before_arrow));
449 566
450 if (after_arrow) { 567 if (after_arrow) {
451 start_x += (is_horizontal ? before_arrow + arrow->width() : 0); 568 start_x += (is_horizontal ? before_arrow + arrow.width() : 0);
452 start_y += (is_horizontal ? 0 : before_arrow + arrow->height()); 569 start_y += (is_horizontal ? 0 : before_arrow + arrow.height());
453 canvas->TileImageInt(*edge, start_x, start_y, 570 canvas->TileImageInt(edge, start_x, start_y,
454 is_horizontal ? after_arrow : edge->width(), 571 is_horizontal ? after_arrow : edge.width(),
455 is_horizontal ? edge->height() : after_arrow); 572 is_horizontal ? edge.height() : after_arrow);
456 } 573 }
457 } 574 }
458 575
459 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, 576 void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas,
460 float tip_x, 577 float tip_x,
461 float tip_y) const { 578 float tip_y) const {
462 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_); 579 const bool is_horizontal = is_arrow_on_horizontal(arrow_location_);
463 const bool positive_offset = is_horizontal ? 580 const bool positive_offset = is_horizontal ?
464 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_); 581 is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_);
465 const int offset_to_next_vertex = positive_offset ? 582 const int offset_to_next_vertex = positive_offset ?
466 kArrowInteriorHeight : -kArrowInteriorHeight; 583 images_->arrow_interior_height : -images_->arrow_interior_height;
467 584
468 SkPath path; 585 SkPath path;
469 path.incReserve(4); 586 path.incReserve(4);
470 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y)); 587 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y));
471 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), 588 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
472 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 589 SkDoubleToScalar(tip_y + offset_to_next_vertex));
473 if (is_horizontal) { 590 if (is_horizontal) {
474 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex), 591 path.lineTo(SkDoubleToScalar(tip_x - offset_to_next_vertex),
475 SkDoubleToScalar(tip_y + offset_to_next_vertex)); 592 SkDoubleToScalar(tip_y + offset_to_next_vertex));
476 } else { 593 } else {
(...skipping 22 matching lines...) Expand all
499 // contents, which we need to fill with the background color. 616 // contents, which we need to fill with the background color.
500 // NOTE: This doesn't handle an arrow location of "NONE", which has square top 617 // NOTE: This doesn't handle an arrow location of "NONE", which has square top
501 // corners. 618 // corners.
502 SkPaint paint; 619 SkPaint paint;
503 paint.setAntiAlias(true); 620 paint.setAntiAlias(true);
504 paint.setStyle(SkPaint::kFill_Style); 621 paint.setStyle(SkPaint::kFill_Style);
505 paint.setColor(border_->background_color()); 622 paint.setColor(border_->background_color());
506 SkPath path; 623 SkPath path;
507 gfx::Rect bounds(view->GetContentsBounds()); 624 gfx::Rect bounds(view->GetContentsBounds());
508 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness()); 625 bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness());
509 SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); 626 SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius());
510 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); 627 path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius);
511 canvas->DrawPath(path, paint); 628 canvas->DrawPath(path, paint);
512 } 629 }
513 630
514 } // namespace views 631 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698