Chromium Code Reviews| OLD | NEW |
|---|---|
| 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> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "third_party/skia/include/core/SkPaint.h" | 10 #include "third_party/skia/include/core/SkPaint.h" |
| 11 #include "third_party/skia/include/core/SkPath.h" | 11 #include "third_party/skia/include/core/SkPath.h" |
| 12 #include "ui/base/resource/resource_bundle.h" | 12 #include "ui/base/resource/resource_bundle.h" |
| 13 #include "ui/gfx/canvas.h" | 13 #include "ui/gfx/canvas.h" |
| 14 #include "ui/gfx/geometry/rect.h" | 14 #include "ui/gfx/geometry/rect.h" |
| 15 #include "ui/gfx/path.h" | |
| 15 #include "ui/gfx/skia_util.h" | 16 #include "ui/gfx/skia_util.h" |
| 16 #include "ui/resources/grit/ui_resources.h" | 17 #include "ui/resources/grit/ui_resources.h" |
| 17 #include "ui/views/painter.h" | 18 #include "ui/views/painter.h" |
| 18 #include "ui/views/resources/grit/views_resources.h" | 19 #include "ui/views/resources/grit/views_resources.h" |
| 19 #include "ui/views/view.h" | 20 #include "ui/views/view.h" |
| 20 | 21 |
| 21 namespace views { | 22 namespace views { |
| 22 | 23 |
| 23 namespace internal { | 24 namespace internal { |
| 24 | 25 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 135 |
| 135 } // namespace | 136 } // namespace |
| 136 | 137 |
| 137 const int BubbleBorder::kStroke = 1; | 138 const int BubbleBorder::kStroke = 1; |
| 138 | 139 |
| 139 BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color) | 140 BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color) |
| 140 : arrow_(arrow), | 141 : arrow_(arrow), |
| 141 arrow_offset_(0), | 142 arrow_offset_(0), |
| 142 arrow_paint_type_(PAINT_NORMAL), | 143 arrow_paint_type_(PAINT_NORMAL), |
| 143 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), | 144 alignment_(ALIGN_ARROW_TO_MID_ANCHOR), |
| 144 shadow_(shadow), | |
| 145 background_color_(color), | 145 background_color_(color), |
| 146 use_theme_background_color_(false) { | 146 use_theme_background_color_(false) { |
| 147 DCHECK(shadow < SHADOW_COUNT); | 147 // On Mac, use the NO_ASSETS bubble border. WindowServer on Mac is able to |
|
tapted
2016/01/28 05:59:22
nit: I think we should have the initializer still,
karandeepb
2016/02/04 03:39:27
Done.
| |
| 148 images_ = GetBorderImages(shadow); | 148 // generate drop shadows for dialogs, hence we don't use raster shadows. |
| 149 #if defined(OS_MACOSX) | |
| 150 shadow_ = NO_ASSETS; | |
| 151 #else | |
| 152 shadow_ = shadow; | |
| 153 #endif // OS_MACOSX | |
| 154 DCHECK(shadow_ < SHADOW_COUNT); | |
| 155 images_ = GetBorderImages(shadow_); | |
| 149 } | 156 } |
| 150 | 157 |
| 151 BubbleBorder::~BubbleBorder() {} | 158 BubbleBorder::~BubbleBorder() {} |
| 152 | 159 |
| 153 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, | 160 gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, |
| 154 const gfx::Size& contents_size) const { | 161 const gfx::Size& contents_size) const { |
| 155 int x = anchor_rect.x(); | 162 int x = anchor_rect.x(); |
| 156 int y = anchor_rect.y(); | 163 int y = anchor_rect.y(); |
| 157 int w = anchor_rect.width(); | 164 int w = anchor_rect.width(); |
| 158 int h = anchor_rect.height(); | 165 int h = anchor_rect.height(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 border_size.width() : border_size.height(); | 211 border_size.width() : border_size.height(); |
| 205 if (is_arrow_at_center(arrow_) && arrow_offset_ == 0) | 212 if (is_arrow_at_center(arrow_) && arrow_offset_ == 0) |
| 206 return edge_length / 2; | 213 return edge_length / 2; |
| 207 | 214 |
| 208 // Calculate the minimum offset to not overlap arrow and corner images. | 215 // Calculate the minimum offset to not overlap arrow and corner images. |
| 209 const int min = images_->border_thickness + (images_->arrow_width / 2); | 216 const int min = images_->border_thickness + (images_->arrow_width / 2); |
| 210 // Ensure the returned value will not cause image overlap, if possible. | 217 // Ensure the returned value will not cause image overlap, if possible. |
| 211 return std::max(min, std::min(arrow_offset_, edge_length - min)); | 218 return std::max(min, std::min(arrow_offset_, edge_length - min)); |
| 212 } | 219 } |
| 213 | 220 |
| 221 void BubbleBorder::GetArrowMask(const gfx::Rect& view_bounds, | |
| 222 gfx::Path* mask) const { | |
| 223 if (!has_arrow(arrow_) || arrow_paint_type_ != PAINT_NORMAL) | |
| 224 return; | |
| 225 | |
| 226 return GetArrowMaskFromArrowBounds(GetArrowRect(view_bounds), mask); | |
| 227 } | |
| 228 | |
| 214 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { | 229 void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) { |
| 215 gfx::Rect bounds(view.GetContentsBounds()); | 230 gfx::Rect bounds(view.GetContentsBounds()); |
| 216 bounds.Inset(-GetBorderThickness(), -GetBorderThickness()); | 231 bounds.Inset(-GetBorderThickness(), -GetBorderThickness()); |
| 217 const gfx::Rect arrow_bounds = GetArrowRect(view.GetLocalBounds()); | 232 const gfx::Rect arrow_bounds = GetArrowRect(view.GetLocalBounds()); |
| 218 if (arrow_bounds.IsEmpty()) { | 233 if (arrow_bounds.IsEmpty()) { |
| 219 if (images_->border_painter) | 234 if (images_->border_painter) |
| 220 Painter::PaintPainterAt(canvas, images_->border_painter.get(), bounds); | 235 Painter::PaintPainterAt(canvas, images_->border_painter.get(), bounds); |
| 221 return; | 236 return; |
| 222 } | 237 } |
| 223 if (!images_->border_painter) { | 238 if (!images_->border_painter) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 321 | 336 |
| 322 // With no assets, return the size enclosing the path filled in DrawArrow(). | 337 // With no assets, return the size enclosing the path filled in DrawArrow(). |
| 323 DCHECK_EQ(2 * images_->arrow_interior_thickness, images_->arrow_width); | 338 DCHECK_EQ(2 * images_->arrow_interior_thickness, images_->arrow_width); |
| 324 int width = images_->arrow_width; | 339 int width = images_->arrow_width; |
| 325 int height = images_->arrow_interior_thickness; | 340 int height = images_->arrow_interior_thickness; |
| 326 if (!is_arrow_on_horizontal(arrow_)) | 341 if (!is_arrow_on_horizontal(arrow_)) |
| 327 std::swap(width, height); | 342 std::swap(width, height); |
| 328 return gfx::Rect(origin, gfx::Size(width, height)); | 343 return gfx::Rect(origin, gfx::Size(width, height)); |
| 329 } | 344 } |
| 330 | 345 |
| 331 void BubbleBorder::DrawArrow(gfx::Canvas* canvas, | 346 void BubbleBorder::GetArrowMaskFromArrowBounds(const gfx::Rect& arrow_bounds, |
| 332 const gfx::Rect& arrow_bounds) const { | 347 SkPath* mask) const { |
| 333 canvas->DrawImageInt(*GetArrowImage(), arrow_bounds.x(), arrow_bounds.y()); | |
| 334 const bool horizontal = is_arrow_on_horizontal(arrow_); | 348 const bool horizontal = is_arrow_on_horizontal(arrow_); |
| 335 const int thickness = images_->arrow_interior_thickness; | 349 const int thickness = images_->arrow_interior_thickness; |
| 336 float tip_x = horizontal ? arrow_bounds.CenterPoint().x() : | 350 float tip_x = horizontal ? arrow_bounds.CenterPoint().x() : |
| 337 is_arrow_on_left(arrow_) ? arrow_bounds.right() - thickness : | 351 is_arrow_on_left(arrow_) ? arrow_bounds.right() - thickness : |
| 338 arrow_bounds.x() + thickness; | 352 arrow_bounds.x() + thickness; |
| 339 float tip_y = !horizontal ? arrow_bounds.CenterPoint().y() + 0.5f : | 353 float tip_y = !horizontal ? arrow_bounds.CenterPoint().y() + 0.5f : |
| 340 is_arrow_on_top(arrow_) ? arrow_bounds.bottom() - thickness : | 354 is_arrow_on_top(arrow_) ? arrow_bounds.bottom() - thickness : |
| 341 arrow_bounds.y() + thickness; | 355 arrow_bounds.y() + thickness; |
| 342 const bool positive_offset = horizontal ? | 356 const bool positive_offset = horizontal ? |
| 343 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_); | 357 is_arrow_on_top(arrow_) : is_arrow_on_left(arrow_); |
| 344 const int offset_to_next_vertex = positive_offset ? | 358 const int offset_to_next_vertex = positive_offset ? |
| 345 images_->arrow_interior_thickness : -images_->arrow_interior_thickness; | 359 images_->arrow_interior_thickness : -images_->arrow_interior_thickness; |
| 346 | 360 |
| 361 mask->incReserve(4); | |
| 362 mask->moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y)); | |
| 363 mask->lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), | |
| 364 SkDoubleToScalar(tip_y + offset_to_next_vertex)); | |
| 365 const int multiplier = horizontal ? 1 : -1; | |
| 366 mask->lineTo(SkDoubleToScalar(tip_x - multiplier * offset_to_next_vertex), | |
| 367 SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex)); | |
| 368 mask->close(); | |
| 369 } | |
| 370 | |
| 371 void BubbleBorder::DrawArrow(gfx::Canvas* canvas, | |
| 372 const gfx::Rect& arrow_bounds) const { | |
| 373 canvas->DrawImageInt(*GetArrowImage(), arrow_bounds.x(), arrow_bounds.y()); | |
| 347 SkPath path; | 374 SkPath path; |
| 348 path.incReserve(4); | 375 GetArrowMaskFromArrowBounds(arrow_bounds, &path); |
| 349 path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y)); | |
| 350 path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex), | |
| 351 SkDoubleToScalar(tip_y + offset_to_next_vertex)); | |
| 352 const int multiplier = horizontal ? 1 : -1; | |
| 353 path.lineTo(SkDoubleToScalar(tip_x - multiplier * offset_to_next_vertex), | |
| 354 SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex)); | |
| 355 path.close(); | |
| 356 | |
| 357 SkPaint paint; | 376 SkPaint paint; |
| 358 paint.setStyle(SkPaint::kFill_Style); | 377 paint.setStyle(SkPaint::kFill_Style); |
| 359 paint.setColor(background_color_); | 378 paint.setColor(background_color_); |
| 360 | 379 |
| 361 canvas->DrawPath(path, paint); | 380 canvas->DrawPath(path, paint); |
| 362 } | 381 } |
| 363 | 382 |
| 364 internal::BorderImages* BubbleBorder::GetImagesForTest() const { | 383 internal::BorderImages* BubbleBorder::GetImagesForTest() const { |
| 365 return images_; | 384 return images_; |
| 366 } | 385 } |
| 367 | 386 |
| 368 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { | 387 void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { |
| 369 if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) | 388 if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) |
| 370 canvas->DrawColor(border_->background_color()); | 389 canvas->DrawColor(border_->background_color()); |
| 371 | 390 |
| 372 // Fill the contents with a round-rect region to match the border images. | 391 // Fill the contents with a round-rect region to match the border images. |
| 373 SkPaint paint; | 392 SkPaint paint; |
| 374 paint.setAntiAlias(true); | 393 paint.setAntiAlias(true); |
| 375 paint.setStyle(SkPaint::kFill_Style); | 394 paint.setStyle(SkPaint::kFill_Style); |
| 376 paint.setColor(border_->background_color()); | 395 paint.setColor(border_->background_color()); |
| 377 SkPath path; | 396 SkPath path; |
| 378 gfx::Rect bounds(view->GetLocalBounds()); | 397 gfx::Rect bounds(view->GetLocalBounds()); |
| 379 bounds.Inset(border_->GetInsets()); | 398 bounds.Inset(border_->GetInsets()); |
| 380 | 399 |
| 381 canvas->DrawRoundRect(bounds, border_->GetBorderCornerRadius(), paint); | 400 canvas->DrawRoundRect(bounds, border_->GetBorderCornerRadius(), paint); |
| 382 } | 401 } |
| 383 | 402 |
| 384 } // namespace views | 403 } // namespace views |
| OLD | NEW |