Chromium Code Reviews| Index: ui/views/bubble/bubble_border.cc |
| diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc |
| index 881f082369efbbf2a41259c80a8545da9c2b12e7..6dbe9f65b260e09895221a60c5c8538b87d49dad 100644 |
| --- a/ui/views/bubble/bubble_border.cc |
| +++ b/ui/views/bubble/bubble_border.cc |
| @@ -13,70 +13,152 @@ |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/skia_util.h" |
| +namespace { |
| + |
| +// Stroke size in pixels of borders in image assets. |
| +const int kBorderStrokeSize = 1; |
| + |
| +// Border image resource ids. |
| +const int kShadowImages[] = { |
| + IDR_BUBBLE_SHADOW_L, |
| + IDR_BUBBLE_SHADOW_TL, |
| + IDR_BUBBLE_SHADOW_T, |
| + IDR_BUBBLE_SHADOW_TR, |
| + IDR_BUBBLE_SHADOW_R, |
| + IDR_BUBBLE_SHADOW_BR, |
| + IDR_BUBBLE_SHADOW_B, |
| + IDR_BUBBLE_SHADOW_BL, |
| +}; |
| + |
| +const int kNoShadowImages[] = { |
| + IDR_BUBBLE_L, |
| + IDR_BUBBLE_TL, |
| + IDR_BUBBLE_T, |
| + IDR_BUBBLE_TR, |
| + IDR_BUBBLE_R, |
| + IDR_BUBBLE_BR, |
| + IDR_BUBBLE_B, |
| + IDR_BUBBLE_BL, |
| + IDR_BUBBLE_L_ARROW, |
| + IDR_BUBBLE_T_ARROW, |
| + IDR_BUBBLE_R_ARROW, |
| + IDR_BUBBLE_B_ARROW, |
| +}; |
| + |
| +#if defined(USE_AURA) |
| +const int kBigShadowImages[] = { |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_TOP_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM, |
| + IDR_WINDOW_BUBBLE_SHADOW_BIG_BOTTOM_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_TOP, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_BIG_BOTTOM, |
| +}; |
| + |
| +const int kSmallShadowImages[] = { |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM, |
| + IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_LEFT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_TOP, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_RIGHT, |
| + IDR_WINDOW_BUBBLE_SHADOW_SPIKE_SMALL_BOTTOM, |
| +}; |
| +#endif |
| + |
| +} // namespace |
| + |
| namespace views { |
| struct BubbleBorder::BorderImages { |
| - BorderImages() |
| - : left(NULL), |
| - top_left(NULL), |
| - top(NULL), |
| - top_right(NULL), |
| - right(NULL), |
| - bottom_right(NULL), |
| - bottom(NULL), |
| - bottom_left(NULL), |
| - left_arrow(NULL), |
| - top_arrow(NULL), |
| - right_arrow(NULL), |
| - bottom_arrow(NULL), |
| - border_thickness(0) { |
| + BorderImages(const int image_ids[], |
| + size_t image_ids_size, |
| + int arrow_interior_height, |
| + int border_thickness, |
| + int corner_radius) |
| + : arrow_interior_height(arrow_interior_height), |
| + border_thickness(border_thickness), |
| + corner_radius(corner_radius) { |
| + // Only two possible sizes of image ids array. |
| + DCHECK(image_ids_size == 12 || image_ids_size == 8); |
| + |
| + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| + |
| + left = *rb.GetImageNamed(image_ids[0]).ToImageSkia(); |
|
msw
2012/09/20 17:03:34
I know the ResourceBundle header says GetImageName
xiyuan
2012/09/20 17:30:56
Aha... Thanks for the tip. Reverted back to use Ge
msw
2012/09/20 17:40:09
np, I'm updating the ambiguous comment at https://
|
| + top_left = *rb.GetImageNamed(image_ids[1]).ToImageSkia(); |
| + top = *rb.GetImageNamed(image_ids[2]).ToImageSkia(); |
| + top_right = *rb.GetImageNamed(image_ids[3]).ToImageSkia(); |
| + right = *rb.GetImageNamed(image_ids[4]).ToImageSkia(); |
| + bottom_right = *rb.GetImageNamed(image_ids[5]).ToImageSkia(); |
| + bottom = *rb.GetImageNamed(image_ids[6]).ToImageSkia(); |
| + bottom_left = *rb.GetImageNamed(image_ids[7]).ToImageSkia(); |
| + |
| + if (image_ids_size > 8) { |
| + left_arrow = *rb.GetImageNamed(image_ids[8]).ToImageSkia(); |
| + top_arrow = *rb.GetImageNamed(image_ids[9]).ToImageSkia(); |
| + right_arrow = *rb.GetImageNamed(image_ids[10]).ToImageSkia(); |
| + bottom_arrow = *rb.GetImageNamed(image_ids[11]).ToImageSkia(); |
| + } |
| } |
| - gfx::ImageSkia* left; |
| - gfx::ImageSkia* top_left; |
| - gfx::ImageSkia* top; |
| - gfx::ImageSkia* top_right; |
| - gfx::ImageSkia* right; |
| - gfx::ImageSkia* bottom_right; |
| - gfx::ImageSkia* bottom; |
| - gfx::ImageSkia* bottom_left; |
| - gfx::ImageSkia* left_arrow; |
| - gfx::ImageSkia* top_arrow; |
| - gfx::ImageSkia* right_arrow; |
| - gfx::ImageSkia* bottom_arrow; |
| + gfx::ImageSkia left; |
| + gfx::ImageSkia top_left; |
| + gfx::ImageSkia top; |
| + gfx::ImageSkia top_right; |
| + gfx::ImageSkia right; |
| + gfx::ImageSkia bottom_right; |
| + gfx::ImageSkia bottom; |
| + gfx::ImageSkia bottom_left; |
| + |
| + gfx::ImageSkia left_arrow; |
| + gfx::ImageSkia top_arrow; |
| + gfx::ImageSkia right_arrow; |
| + gfx::ImageSkia bottom_arrow; |
| + |
| + int arrow_interior_height; // The height inside the arrow image, in pixels. |
| int border_thickness; |
| + int corner_radius; |
| }; |
| // static |
| -struct BubbleBorder::BorderImages* BubbleBorder::normal_images_ = NULL; |
| -struct BubbleBorder::BorderImages* BubbleBorder::shadow_images_ = NULL; |
| - |
| -// The height inside the arrow image, in pixels. |
| -static const int kArrowInteriorHeight = 7; |
| +struct BubbleBorder::BorderImages* |
| + BubbleBorder::border_images_[SHADOW_COUNT] = { NULL }; |
| BubbleBorder::BubbleBorder(ArrowLocation arrow_location, Shadow shadow) |
| : override_arrow_offset_(0), |
| arrow_location_(arrow_location), |
| alignment_(ALIGN_ARROW_TO_MID_ANCHOR), |
| background_color_(SK_ColorWHITE) { |
| + DCHECK(shadow < SHADOW_COUNT); |
| images_ = GetBorderImages(shadow); |
| // Calculate horizontal and vertical insets for arrow by ensuring that |
| // the widest arrow and corner images will have enough room to avoid overlap |
| int offset_x = |
| - (std::max(images_->top_arrow->width(), |
| - images_->bottom_arrow->width()) / 2) + |
| - std::max(std::max(images_->top_left->width(), |
| - images_->top_right->width()), |
| - std::max(images_->bottom_left->width(), |
| - images_->bottom_right->width())); |
| + (std::max(images_->top_arrow.width(), |
| + images_->bottom_arrow.width()) / 2) + |
| + std::max(std::max(images_->top_left.width(), |
| + images_->top_right.width()), |
| + std::max(images_->bottom_left.width(), |
| + images_->bottom_right.width())); |
| int offset_y = |
| - (std::max(images_->left_arrow->height(), |
| - images_->right_arrow->height()) / 2) + |
| - std::max(std::max(images_->top_left->height(), |
| - images_->top_right->height()), |
| - std::max(images_->bottom_left->height(), |
| - images_->bottom_right->height())); |
| + (std::max(images_->left_arrow.height(), |
| + images_->right_arrow.height()) / 2) + |
| + std::max(std::max(images_->top_left.height(), |
| + images_->top_right.height()), |
| + std::max(images_->bottom_left.height(), |
| + images_->bottom_right.height())); |
| arrow_offset_ = std::max(offset_x, offset_y); |
| } |
| @@ -95,39 +177,46 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, |
| border_size.set_height(std::max(border_size.height(), 2 * arrow_offset_)); |
| // Screen position depends on the arrow location. |
| - // The arrow should overlap the target by some amount since there is space |
| - // for shadow between arrow tip and image bounds. |
| - const int kArrowOverlap = 3; |
| + // The bubble should overlap the target by some amount since there is space |
| + // for shadow between arrow tip/bubble border and image bounds. |
| int x = position_relative_to.x(); |
| int y = position_relative_to.y(); |
| int w = position_relative_to.width(); |
| int h = position_relative_to.height(); |
| - int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : |
| - arrow_offset_; |
| + |
| + const int arrow_size = images_->arrow_interior_height + kBorderStrokeSize; |
| + const int arrow_offset = GetArrowOffset(border_size); |
| // Calculate bubble x coordinate. |
| switch (arrow_location_) { |
| case TOP_LEFT: |
| case BOTTOM_LEFT: |
| x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? w / 2 - arrow_offset : |
| - -kArrowOverlap; |
| + -(images_->left.width() - kBorderStrokeSize); |
| break; |
| case TOP_RIGHT: |
| case BOTTOM_RIGHT: |
| x += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? |
| w / 2 + arrow_offset - border_size.width() + 1 : |
| - w - border_size.width() + kArrowOverlap; |
| + w - border_size.width() + images_->right.width() - kBorderStrokeSize; |
| break; |
| case LEFT_TOP: |
| + case LEFT_CENTER: |
| case LEFT_BOTTOM: |
| - x += w - kArrowOverlap; |
| + x += w - (images_->left_arrow.width() - arrow_size); |
| break; |
| case RIGHT_TOP: |
| + case RIGHT_CENTER: |
| case RIGHT_BOTTOM: |
| - x += kArrowOverlap - border_size.width(); |
| + x += images_->right_arrow.width() - arrow_size - border_size.width(); |
| + break; |
| + |
| + case TOP_CENTER: |
| + case BOTTOM_CENTER: |
| + x += w / 2 - arrow_offset; |
| break; |
| case NONE: |
| @@ -139,26 +228,35 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, |
| // Calculate bubble y coordinate. |
| switch (arrow_location_) { |
| case TOP_LEFT: |
| + case TOP_CENTER: |
| case TOP_RIGHT: |
| - y += h - kArrowOverlap; |
| + y += h - (images_->top_arrow.height() - arrow_size); |
| break; |
| case BOTTOM_LEFT: |
| + case BOTTOM_CENTER: |
| case BOTTOM_RIGHT: |
| - y += kArrowOverlap - border_size.height(); |
| + y += images_->bottom_arrow.height() - arrow_size - |
| + border_size.height(); |
| break; |
| case LEFT_TOP: |
| case RIGHT_TOP: |
| y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? h / 2 - arrow_offset : |
| - -kArrowOverlap; |
| + -(images_->top.height() - kBorderStrokeSize); |
| break; |
| case LEFT_BOTTOM: |
| case RIGHT_BOTTOM: |
| y += alignment_ == ALIGN_ARROW_TO_MID_ANCHOR ? |
| h / 2 + arrow_offset - border_size.height() + 1 : |
| - h - border_size.height() + kArrowOverlap; |
| + h - border_size.height() + images_->bottom.height() - |
| + kBorderStrokeSize; |
| + break; |
| + |
| + case LEFT_CENTER: |
| + case RIGHT_CENTER: |
| + y += h / 2 - arrow_offset; |
| break; |
| case NONE: |
| @@ -179,29 +277,33 @@ void BubbleBorder::GetInsets(gfx::Insets* insets) const { |
| void BubbleBorder::GetInsetsForArrowLocation(gfx::Insets* insets, |
| ArrowLocation arrow_loc) const { |
| - int top = images_->top->height(); |
| - int bottom = images_->bottom->height(); |
| - int left = images_->left->width(); |
| - int right = images_->right->width(); |
| + int top = images_->top.height(); |
| + int bottom = images_->bottom.height(); |
| + int left = images_->left.width(); |
| + int right = images_->right.width(); |
| switch (arrow_loc) { |
| case TOP_LEFT: |
| + case TOP_CENTER: |
| case TOP_RIGHT: |
| - top = std::max(top, images_->top_arrow->height()); |
| + top = std::max(top, images_->top_arrow.height()); |
| break; |
| case BOTTOM_LEFT: |
| + case BOTTOM_CENTER: |
| case BOTTOM_RIGHT: |
| - bottom = std::max(bottom, images_->bottom_arrow->height()); |
| + bottom = std::max(bottom, images_->bottom_arrow.height()); |
| break; |
| case LEFT_TOP: |
| + case LEFT_CENTER: |
| case LEFT_BOTTOM: |
| - left = std::max(left, images_->left_arrow->width()); |
| + left = std::max(left, images_->left_arrow.width()); |
| break; |
| case RIGHT_TOP: |
| + case RIGHT_CENTER: |
| case RIGHT_BOTTOM: |
| - right = std::max(right, images_->right_arrow->width()); |
| + right = std::max(right, images_->right_arrow.width()); |
| break; |
| case NONE: |
| @@ -216,73 +318,85 @@ int BubbleBorder::GetBorderThickness() const { |
| return images_->border_thickness; |
| } |
| -int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { |
| - gfx::Size border_size(contents_size); |
| - gfx::Insets insets; |
| - GetInsets(&insets); |
| - border_size.Enlarge(insets.left() + insets.right(), |
| - insets.top() + insets.bottom()); |
| - offset = std::max(arrow_offset_, |
| - std::min(offset, (is_arrow_on_horizontal(arrow_location_) ? |
| +int BubbleBorder::GetBorderCornerRadius() const { |
| + return images_->corner_radius; |
| +} |
| + |
| +int BubbleBorder::GetArrowOffset(const gfx::Size& border_size) const { |
| + int arrow_offset = arrow_offset_; |
| + if (override_arrow_offset_) { |
| + arrow_offset = override_arrow_offset_; |
| + } else if (is_arrow_at_center(arrow_location_)) { |
| + if (is_arrow_on_horizontal(arrow_location_)) |
| + arrow_offset = border_size.width() / 2; |
| + else |
| + arrow_offset = border_size.height() / 2; |
| + } |
| + |
| + // |arrow_offset_| contains the minimum offset required to draw border images |
| + // correctly. It's defined in terms of number of pixels from the beginning of |
| + // the edge. The maximum arrow offset is the edge size - |arrow_offset_|. The |
| + // following statement clamps the calculated arrow offset within that range. |
| + return std::max(arrow_offset_, |
| + std::min(arrow_offset, (is_arrow_on_horizontal(arrow_location_) ? |
| border_size.width() : border_size.height()) - arrow_offset_)); |
| - override_arrow_offset_ = offset; |
| - return override_arrow_offset_; |
| } |
| // static |
| BubbleBorder::BorderImages* BubbleBorder::GetBorderImages(Shadow shadow) { |
| - if (shadow == SHADOW && shadow_images_ == NULL) { |
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| - shadow_images_ = new BorderImages(); |
| - shadow_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_L); |
| - shadow_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TL); |
| - shadow_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_T); |
| - shadow_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_TR); |
| - shadow_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_R); |
| - shadow_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BR); |
| - shadow_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_B); |
| - shadow_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_SHADOW_BL); |
| - shadow_images_->left_arrow = new gfx::ImageSkia(); |
| - shadow_images_->top_arrow = new gfx::ImageSkia(); |
| - shadow_images_->right_arrow = new gfx::ImageSkia(); |
| - shadow_images_->bottom_arrow = new gfx::ImageSkia(); |
| - shadow_images_->border_thickness = 10; |
| - } else if (shadow == NO_SHADOW && normal_images_ == NULL) { |
| - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| - normal_images_ = new BorderImages(); |
| - normal_images_->left = rb.GetImageSkiaNamed(IDR_BUBBLE_L); |
| - normal_images_->top_left = rb.GetImageSkiaNamed(IDR_BUBBLE_TL); |
| - normal_images_->top = rb.GetImageSkiaNamed(IDR_BUBBLE_T); |
| - normal_images_->top_right = rb.GetImageSkiaNamed(IDR_BUBBLE_TR); |
| - normal_images_->right = rb.GetImageSkiaNamed(IDR_BUBBLE_R); |
| - normal_images_->bottom_right = rb.GetImageSkiaNamed(IDR_BUBBLE_BR); |
| - normal_images_->bottom = rb.GetImageSkiaNamed(IDR_BUBBLE_B); |
| - normal_images_->bottom_left = rb.GetImageSkiaNamed(IDR_BUBBLE_BL); |
| - normal_images_->left_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_L_ARROW); |
| - normal_images_->top_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_T_ARROW); |
| - normal_images_->right_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_R_ARROW); |
| - normal_images_->bottom_arrow = rb.GetImageSkiaNamed(IDR_BUBBLE_B_ARROW); |
| - normal_images_->border_thickness = 0; |
| + CHECK_LT(shadow, SHADOW_COUNT); |
| + |
| + struct BorderImages*& images = border_images_[shadow]; |
| + if (images) |
| + return images; |
| + |
| + switch (shadow) { |
| + case SHADOW: |
| + images = new BorderImages(kShadowImages, |
| + arraysize(kShadowImages), |
| + 0, 10, 4); |
| + break; |
| + case NO_SHADOW: |
| + images = new BorderImages(kNoShadowImages, |
| + arraysize(kNoShadowImages), |
| + 7, 0, 4); |
| + break; |
| +#if defined(USE_AURA) |
| + case BIG_SHADOW: |
| + images = new BorderImages(kBigShadowImages, |
| + arraysize(kBigShadowImages), |
| + 9, 0, 3); |
| + break; |
| + case SMALL_SHADOW: |
| + images = new BorderImages(kSmallShadowImages, |
| + arraysize(kSmallShadowImages), |
| + 9, 0, 3); |
| + break; |
| +#endif |
| + case SHADOW_COUNT: |
| + NOTREACHED(); |
| + break; |
| } |
| - return shadow == SHADOW ? shadow_images_ : normal_images_; |
| + |
| + return images; |
| } |
| BubbleBorder::~BubbleBorder() {} |
| void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| // Convenience shorthand variables. |
| - const int tl_width = images_->top_left->width(); |
| - const int tl_height = images_->top_left->height(); |
| - const int t_height = images_->top->height(); |
| - const int tr_width = images_->top_right->width(); |
| - const int tr_height = images_->top_right->height(); |
| - const int l_width = images_->left->width(); |
| - const int r_width = images_->right->width(); |
| - const int br_width = images_->bottom_right->width(); |
| - const int br_height = images_->bottom_right->height(); |
| - const int b_height = images_->bottom->height(); |
| - const int bl_width = images_->bottom_left->width(); |
| - const int bl_height = images_->bottom_left->height(); |
| + const int tl_width = images_->top_left.width(); |
| + const int tl_height = images_->top_left.height(); |
| + const int t_height = images_->top.height(); |
| + const int tr_width = images_->top_right.width(); |
| + const int tr_height = images_->top_right.height(); |
| + const int l_width = images_->left.width(); |
| + const int r_width = images_->right.width(); |
| + const int br_width = images_->bottom_right.width(); |
| + const int br_height = images_->bottom_right.height(); |
| + const int b_height = images_->bottom.height(); |
| + const int bl_width = images_->bottom_left.width(); |
| + const int bl_height = images_->bottom_left.height(); |
| gfx::Insets insets; |
| GetInsets(&insets); |
| @@ -293,29 +407,31 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| const int height = bottom - top; |
| const int width = right - left; |
| - // |arrow_offset| is offset of arrow from the begining of the edge. |
| - int arrow_offset = arrow_offset_; |
| - if (override_arrow_offset_) |
| - arrow_offset = override_arrow_offset_; |
| - else if (is_arrow_on_horizontal(arrow_location_) && |
| - !is_arrow_on_left(arrow_location_)) { |
| - arrow_offset = view.width() - arrow_offset - 1; |
| - } else if (!is_arrow_on_horizontal(arrow_location_) && |
| - !is_arrow_on_top(arrow_location_)) { |
| - arrow_offset = view.height() - arrow_offset - 1; |
| + // |arrow_offset| is offset of arrow from the beginning of the edge. |
| + int arrow_offset = GetArrowOffset(view.size()); |
| + if (!is_arrow_at_center(arrow_location_)) { |
| + if (is_arrow_on_horizontal(arrow_location_) && |
| + !is_arrow_on_left(arrow_location_)) { |
|
msw
2012/09/20 00:07:23
nit: indent one more space.
xiyuan
2012/09/20 16:56:51
Done.
|
| + arrow_offset = view.width() - arrow_offset - 1; |
| + } else if (!is_arrow_on_horizontal(arrow_location_) && |
| + !is_arrow_on_top(arrow_location_)) { |
| + arrow_offset = view.height() - arrow_offset - 1; |
| + } |
| } |
| // Left edge. |
| - if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { |
| + if (arrow_location_ == LEFT_TOP || |
| + arrow_location_ == LEFT_CENTER || |
| + arrow_location_ == LEFT_BOTTOM) { |
| int start_y = top + tl_height; |
| int before_arrow = |
| - arrow_offset - start_y - images_->left_arrow->height() / 2; |
| + arrow_offset - start_y - images_->left_arrow.height() / 2; |
| int after_arrow = height - tl_height - bl_height - |
| - images_->left_arrow->height() - before_arrow; |
| + images_->left_arrow.height() - before_arrow; |
| // Shift tip coordinates half pixel so that skia draws the tip correctly. |
| DrawArrowInterior(canvas, |
| - images_->left_arrow->width() - kArrowInteriorHeight - 0.5f, |
| - start_y + before_arrow + images_->left_arrow->height() / 2 - 0.5f); |
| + images_->left_arrow.width() - images_->arrow_interior_height - 0.5f, |
| + start_y + before_arrow + images_->left_arrow.height() / 2 - 0.5f); |
| DrawEdgeWithArrow(canvas, |
| false, |
| images_->left, |
| @@ -324,24 +440,26 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| start_y, |
| before_arrow, |
| after_arrow, |
| - images_->left->width() - images_->left_arrow->width()); |
| + images_->left.width() - images_->left_arrow.width()); |
| } else { |
| - canvas->TileImageInt(*images_->left, left, top + tl_height, l_width, |
| + canvas->TileImageInt(images_->left, left, top + tl_height, l_width, |
| height - tl_height - bl_height); |
| } |
| // Top left corner. |
| - canvas->DrawImageInt(*images_->top_left, left, top); |
| + canvas->DrawImageInt(images_->top_left, left, top); |
| // Top edge. |
| - if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { |
| + if (arrow_location_ == TOP_LEFT || |
| + arrow_location_ == TOP_CENTER || |
| + arrow_location_ == TOP_RIGHT) { |
| int start_x = left + tl_width; |
| - int before_arrow = arrow_offset - start_x - images_->top_arrow->width() / 2; |
| + int before_arrow = arrow_offset - start_x - images_->top_arrow.width() / 2; |
| int after_arrow = width - tl_width - tr_width - |
| - images_->top_arrow->width() - before_arrow; |
| + images_->top_arrow.width() - before_arrow; |
| DrawArrowInterior(canvas, |
| - start_x + before_arrow + images_->top_arrow->width() / 2, |
| - images_->top_arrow->height() - kArrowInteriorHeight); |
| + start_x + before_arrow + images_->top_arrow.width() / 2, |
| + images_->top_arrow.height() - images_->arrow_interior_height); |
| DrawEdgeWithArrow(canvas, |
| true, |
| images_->top, |
| @@ -350,26 +468,28 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| top, |
| before_arrow, |
| after_arrow, |
| - images_->top->height() - images_->top_arrow->height()); |
| + images_->top.height() - images_->top_arrow.height()); |
| } else { |
| - canvas->TileImageInt(*images_->top, left + tl_width, top, |
| + canvas->TileImageInt(images_->top, left + tl_width, top, |
| width - tl_width - tr_width, t_height); |
| } |
| // Top right corner. |
| - canvas->DrawImageInt(*images_->top_right, right - tr_width, top); |
| + canvas->DrawImageInt(images_->top_right, right - tr_width, top); |
| // Right edge. |
| - if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { |
| + if (arrow_location_ == RIGHT_TOP || |
| + arrow_location_ == RIGHT_CENTER || |
| + arrow_location_ == RIGHT_BOTTOM) { |
| int start_y = top + tr_height; |
| int before_arrow = |
| - arrow_offset - start_y - images_->right_arrow->height() / 2; |
| + arrow_offset - start_y - images_->right_arrow.height() / 2; |
| int after_arrow = height - tl_height - bl_height - |
| - images_->right_arrow->height() - before_arrow; |
| + images_->right_arrow.height() - before_arrow; |
| // Shift tip coordinates half pixel so that skia draws the tip correctly. |
| DrawArrowInterior(canvas, |
| - right - r_width + kArrowInteriorHeight - 0.5f, |
| - start_y + before_arrow + images_->right_arrow->height() / 2 - 0.5f); |
| + right - r_width + images_->arrow_interior_height - 0.5f, |
| + start_y + before_arrow + images_->right_arrow.height() / 2 - 0.5f); |
| DrawEdgeWithArrow(canvas, |
| false, |
| images_->right, |
| @@ -380,25 +500,27 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| after_arrow, |
| 0); |
| } else { |
| - canvas->TileImageInt(*images_->right, right - r_width, top + tr_height, |
| + canvas->TileImageInt(images_->right, right - r_width, top + tr_height, |
| r_width, height - tr_height - br_height); |
| } |
| // Bottom right corner. |
| - canvas->DrawImageInt(*images_->bottom_right, |
| + canvas->DrawImageInt(images_->bottom_right, |
| right - br_width, |
| bottom - br_height); |
| // Bottom edge. |
| - if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { |
| + if (arrow_location_ == BOTTOM_LEFT || |
| + arrow_location_ == BOTTOM_CENTER || |
| + arrow_location_ == BOTTOM_RIGHT) { |
| int start_x = left + bl_width; |
| int before_arrow = |
| - arrow_offset - start_x - images_->bottom_arrow->width() / 2; |
| + arrow_offset - start_x - images_->bottom_arrow.width() / 2; |
| int after_arrow = width - bl_width - br_width - |
| - images_->bottom_arrow->width() - before_arrow; |
| + images_->bottom_arrow.width() - before_arrow; |
| DrawArrowInterior(canvas, |
| - start_x + before_arrow + images_->bottom_arrow->width() / 2, |
| - bottom - b_height + kArrowInteriorHeight); |
| + start_x + before_arrow + images_->bottom_arrow.width() / 2, |
| + bottom - b_height + images_->arrow_interior_height); |
| DrawEdgeWithArrow(canvas, |
| true, |
| images_->bottom, |
| @@ -409,18 +531,18 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { |
| after_arrow, |
| 0); |
| } else { |
| - canvas->TileImageInt(*images_->bottom, left + bl_width, bottom - b_height, |
| + canvas->TileImageInt(images_->bottom, left + bl_width, bottom - b_height, |
| width - bl_width - br_width, b_height); |
| } |
| // Bottom left corner. |
| - canvas->DrawImageInt(*images_->bottom_left, left, bottom - bl_height); |
| + canvas->DrawImageInt(images_->bottom_left, left, bottom - bl_height); |
| } |
| void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas, |
| bool is_horizontal, |
| - gfx::ImageSkia* edge, |
| - gfx::ImageSkia* arrow, |
| + const gfx::ImageSkia& edge, |
| + const gfx::ImageSkia& arrow, |
| int start_x, |
| int start_y, |
| int before_arrow, |
| @@ -438,21 +560,21 @@ void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas, |
| * before_arrow ─┘ └─ after_arrow |
| */ |
| if (before_arrow) { |
| - canvas->TileImageInt(*edge, start_x, start_y, |
| - is_horizontal ? before_arrow : edge->width(), |
| - is_horizontal ? edge->height() : before_arrow); |
| + canvas->TileImageInt(edge, start_x, start_y, |
| + is_horizontal ? before_arrow : edge.width(), |
| + is_horizontal ? edge.height() : before_arrow); |
| } |
| - canvas->DrawImageInt(*arrow, |
| + canvas->DrawImageInt(arrow, |
| start_x + (is_horizontal ? before_arrow : offset), |
| start_y + (is_horizontal ? offset : before_arrow)); |
| if (after_arrow) { |
| - start_x += (is_horizontal ? before_arrow + arrow->width() : 0); |
| - start_y += (is_horizontal ? 0 : before_arrow + arrow->height()); |
| - canvas->TileImageInt(*edge, start_x, start_y, |
| - is_horizontal ? after_arrow : edge->width(), |
| - is_horizontal ? edge->height() : after_arrow); |
| + start_x += (is_horizontal ? before_arrow + arrow.width() : 0); |
| + start_y += (is_horizontal ? 0 : before_arrow + arrow.height()); |
| + canvas->TileImageInt(edge, start_x, start_y, |
| + is_horizontal ? after_arrow : edge.width(), |
| + is_horizontal ? edge.height() : after_arrow); |
| } |
| } |
| @@ -463,7 +585,7 @@ void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, |
| const bool positive_offset = is_horizontal ? |
| is_arrow_on_top(arrow_location_) : is_arrow_on_left(arrow_location_); |
| const int offset_to_next_vertex = positive_offset ? |
| - kArrowInteriorHeight : -kArrowInteriorHeight; |
| + images_->arrow_interior_height : -images_->arrow_interior_height; |
| SkPath path; |
| path.incReserve(4); |
| @@ -506,7 +628,7 @@ void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { |
| SkPath path; |
| gfx::Rect bounds(view->GetContentsBounds()); |
| bounds.Inset(-border_->GetBorderThickness(), -border_->GetBorderThickness()); |
| - SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); |
| + SkScalar radius = SkIntToScalar(border_->GetBorderCornerRadius()); |
| path.addRoundRect(gfx::RectToSkRect(bounds), radius, radius); |
| canvas->DrawPath(path, paint); |
| } |