Index: ui/views/bubble/bubble_border.cc |
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc |
index d7c7149b9f2b6063593eaf09698e67f4379a0c3c..673862d363929f1b43f9b8de146c5fbfbbfdf91e 100644 |
--- a/ui/views/bubble/bubble_border.cc |
+++ b/ui/views/bubble/bubble_border.cc |
@@ -60,6 +60,11 @@ BorderImages::~BorderImages() {} |
namespace { |
+// The border is stroked at 1px, but for the purposes of reserving space we have |
+// to deal in dip coordinates, so round up to 1dip. |
+const int kBorderThicknessDip = 1; |
+const int kBorderStrokeThicknessPx = 1; |
+ |
// Blur and offset values for the two shadows drawn around each dialog. The |
// values are all in dip. |
const int kSmallShadowVerticalOffset = 2; |
@@ -211,6 +216,15 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, |
(arrow_ == TOP_RIGHT || arrow_ == TOP_LEFT || arrow_ == BOTTOM_CENTER || |
arrow_ == LEFT_CENTER || arrow_ == RIGHT_CENTER)) { |
gfx::Rect contents_bounds(contents_size); |
+ // Apply the border part of the inset before calculating coordinates because |
+ // the border should align with the anchor's border. For the purposes of |
+ // positioning, the border is rounded up to a dip, which may mean we have |
+ // misalignment in scale factors greater than 1. |
+ // TODO(estade): when it becomes possible to provide px bounds instead of |
+ // dip bounds, fix this. |
+ const gfx::Insets border_insets = gfx::Insets(kBorderThicknessDip); |
+ const gfx::Insets shadow_insets = GetInsets() - border_insets; |
+ contents_bounds.Inset(-border_insets); |
if (arrow_ == TOP_RIGHT) { |
contents_bounds += |
anchor_rect.bottom_right() - contents_bounds.top_right(); |
@@ -224,7 +238,7 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect, |
} else if (arrow_ == RIGHT_CENTER) { |
contents_bounds += LeftCenter(anchor_rect) - RightCenter(contents_bounds); |
} |
- contents_bounds.Inset(-GetInsets()); |
+ contents_bounds.Inset(-shadow_insets); |
// |arrow_offset_| is used to adjust bubbles that would normally be |
// partially offscreen. |
contents_bounds += gfx::Vector2d(-arrow_offset_, 0); |
@@ -352,6 +366,7 @@ gfx::Insets BubbleBorder::GetInsets() const { |
gfx::Insets blur(kLargeShadowBlur); |
gfx::Insets offset(-kLargeShadowVerticalOffset, 0, |
kLargeShadowVerticalOffset, 0); |
+ gfx::Insets border(kBorderThicknessDip); |
return blur + offset; |
} |
@@ -506,19 +521,21 @@ void BubbleBorder::PaintMd(const View& view, gfx::Canvas* canvas) { |
paint.setColor(SkColorSetA(SK_ColorBLACK, 0x26)); |
paint.setAntiAlias(true); |
- gfx::Rect bounds(view.GetLocalBounds()); |
+ gfx::RectF bounds(view.GetLocalBounds()); |
bounds.Inset(GetInsets()); |
- SkRRect r_rect = |
- SkRRect::MakeRectXY(gfx::RectToSkRect(bounds), GetBorderCornerRadius(), |
- GetBorderCornerRadius()); |
// Clip out a round rect so the fill and shadow don't draw over the contents |
// of the bubble. |
- SkRRect clip_r_rect = r_rect; |
- // Stroke width is a single pixel at any scale factor. |
- const SkScalar one_pixel = SkFloatToScalar(1 / canvas->image_scale()); |
- clip_r_rect.inset(one_pixel, one_pixel); |
+ SkRRect clip_r_rect = |
+ SkRRect::MakeRectXY(gfx::RectFToSkRect(bounds), GetBorderCornerRadius(), |
+ GetBorderCornerRadius()); |
canvas->sk_canvas()->clipRRect(clip_r_rect, SkRegion::kDifference_Op, |
true /*doAntiAlias*/); |
+ |
+ // The border is drawn outside the content area. |
+ SkRRect r_rect = clip_r_rect; |
+ const SkScalar one_pixel = |
+ SkFloatToScalar(kBorderStrokeThicknessPx / canvas->image_scale()); |
+ r_rect.inset(-one_pixel, -one_pixel); |
canvas->sk_canvas()->drawRRect(r_rect, paint); |
} |
@@ -538,12 +555,6 @@ void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { |
SkPath path; |
gfx::RectF bounds(view->GetLocalBounds()); |
bounds.Inset(gfx::InsetsF(border_->GetInsets())); |
- if (UseMd()) { |
- // The border is 1px at all scale factors. Leave room for it. It's partially |
- // transparent, so we don't want to draw any background underneath it. |
- const SkScalar one_pixel = SkFloatToScalar(1 / canvas->image_scale()); |
- bounds.Inset(gfx::InsetsF(one_pixel)); |
- } |
canvas->DrawRoundRect(bounds, border_->GetBorderCornerRadius(), paint); |
} |