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 "chrome/browser/ui/views/infobars/infobar_background.h" | 5 #include "chrome/browser/ui/views/infobars/infobar_background.h" |
| 6 | 6 |
| 7 #include "chrome/browser/ui/infobar_container_delegate.h" | 7 #include "chrome/browser/ui/infobar_container_delegate.h" |
| 8 #include "chrome/browser/ui/views/infobars/infobar_view.h" | 8 #include "chrome/browser/ui/views/infobars/infobar_view.h" |
| 9 #include "components/infobars/core/infobar.h" | 9 #include "components/infobars/core/infobar.h" |
| 10 #include "third_party/skia/include/effects/SkGradientShader.h" | 10 #include "third_party/skia/include/effects/SkGradientShader.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 view->width(), InfoBarContainerDelegate::kSeparatorLineHeight), | 66 view->width(), InfoBarContainerDelegate::kSeparatorLineHeight), |
| 67 separator_color); | 67 separator_color); |
| 68 } | 68 } |
| 69 | 69 |
| 70 void InfoBarBackground::PaintMd(gfx::Canvas* canvas, views::View* view) const { | 70 void InfoBarBackground::PaintMd(gfx::Canvas* canvas, views::View* view) const { |
| 71 InfoBarView* infobar = static_cast<InfoBarView*>(view); | 71 InfoBarView* infobar = static_cast<InfoBarView*>(view); |
| 72 const infobars::InfoBarContainer::Delegate* delegate = | 72 const infobars::InfoBarContainer::Delegate* delegate = |
| 73 infobar->container_delegate(); | 73 infobar->container_delegate(); |
| 74 SkPath stroke_path, fill_path; | 74 SkPath stroke_path, fill_path; |
| 75 SkColor separator_color = SK_ColorBLACK; | 75 SkColor separator_color = SK_ColorBLACK; |
| 76 gfx::ScopedCanvas scoped(canvas); | |
| 77 // Undo the scale factor so we can stroke with a width of 1px (not 1dp). | |
| 78 const float dsf = canvas->UndoDeviceScaleFactor(); | |
| 79 // Always scale to a whole number to make sure strokes are sharp. | |
| 80 // For some fractional DSFs, view size rounding issues may cause there to be a | |
| 81 // gap above the infobar (below the horizontal stroke painted by the previous | |
| 82 // infobar or the toolbar). We use floor here to "pull" the fill region up a | |
| 83 // pixel and bridge the gap. Sometimes this will be 1px too high, so we also | |
| 84 // re-draw the horizontal portions of the top separator in case this floor | |
| 85 // operation has covered it up. For whole-number DSFs, the floor should have | |
| 86 // no effect. | |
| 87 auto scale = [dsf](int dimension) { return std::floor(dimension * dsf); }; | |
| 88 SkScalar arrow_height = scale(infobar->arrow_height()); | |
| 89 SkScalar infobar_width = scale(infobar->width()); | |
| 76 if (delegate) { | 90 if (delegate) { |
| 77 separator_color = delegate->GetInfoBarSeparatorColor(); | 91 separator_color = delegate->GetInfoBarSeparatorColor(); |
| 78 int arrow_x; | 92 int arrow_x; |
| 79 if (delegate->DrawInfoBarArrows(&arrow_x) && infobar->arrow_height() > 0) { | 93 if (delegate->DrawInfoBarArrows(&arrow_x) && infobar->arrow_height() > 0) { |
| 80 SkScalar arrow_fill_height = SkIntToScalar(infobar->arrow_height()); | 94 // Compensate for the fact that a relative movement of n creates a line of |
| 81 SkScalar arrow_fill_half_width = | 95 // length n + 1. |
|
Peter Kasting
2016/07/28 21:18:52
Nit: "...once the path is placed on pixel centers
| |
| 82 SkIntToScalar(infobar->arrow_half_width()); | 96 SkScalar r_arrow_half_width = scale(infobar->arrow_half_width()) - 1; |
| 83 stroke_path.moveTo(SkIntToScalar(arrow_x) - arrow_fill_half_width, | 97 SkScalar r_arrow_height = arrow_height - 1; |
| 84 SkIntToScalar(infobar->arrow_height())); | 98 SkScalar arrow_tip_x = scale(arrow_x); |
| 85 stroke_path.rLineTo(arrow_fill_half_width, -arrow_fill_height); | 99 stroke_path.moveTo(0, r_arrow_height); |
| 86 stroke_path.rLineTo(arrow_fill_half_width, arrow_fill_height); | 100 stroke_path.lineTo(arrow_tip_x - r_arrow_half_width, r_arrow_height); |
| 101 stroke_path.lineTo(arrow_tip_x, 0); | |
| 102 stroke_path.lineTo(arrow_tip_x + r_arrow_half_width, r_arrow_height); | |
| 103 stroke_path.lineTo(infobar_width, r_arrow_height); | |
|
Peter Kasting
2016/07/28 21:18:52
Nit: You want "infobar_width - 1" here.
| |
| 104 | |
| 105 // Add SK_ScalarHalf to both axes to place the path on pixel centers. | |
| 106 stroke_path.offset(SK_ScalarHalf, SK_ScalarHalf); | |
| 87 | 107 |
| 88 fill_path = stroke_path; | 108 fill_path = stroke_path; |
| 89 fill_path.close(); | 109 fill_path.close(); |
| 90 } | 110 } |
| 91 } | 111 } |
| 92 fill_path.addRect(0, SkIntToScalar(infobar->arrow_height()), | 112 fill_path.addRect(0, arrow_height, infobar_width, scale(infobar->height())); |
| 93 SkIntToScalar(infobar->width()), | |
| 94 SkIntToScalar(infobar->height())); | |
| 95 | |
| 96 gfx::ScopedCanvas scoped(canvas); | |
| 97 // Undo the scale factor so we can stroke with a width of 1px (not 1dp). | |
| 98 const float scale = canvas->UndoDeviceScaleFactor(); | |
| 99 // View bounds are in dp. Manually scale for px. | |
| 100 gfx::SizeF view_size_px = gfx::ScaleSize(gfx::SizeF(view->size()), scale); | |
| 101 | |
| 102 SkPaint fill; | 113 SkPaint fill; |
| 103 fill.setStyle(SkPaint::kFill_Style); | 114 fill.setStyle(SkPaint::kFill_Style); |
| 104 fill.setColor(top_color_); | 115 fill.setColor(top_color_); |
| 105 | 116 canvas->DrawPath(fill_path, fill); |
| 106 SkCanvas* canvas_skia = canvas->sk_canvas(); | |
| 107 // The paths provided by the above calculations are in dp. Manually scale for | |
| 108 // px. | |
| 109 SkMatrix dsf_transform; | |
| 110 dsf_transform.setScale(SkFloatToScalar(scale), SkFloatToScalar(scale)); | |
| 111 fill_path.transform(dsf_transform); | |
| 112 // In order to affect exactly the pixels we want, the fill and stroke paths | |
| 113 // need to go through the pixel centers instead of along the pixel | |
| 114 // edges/corners. Skia considers integral coordinates to be the edges between | |
| 115 // pixels, so offset by 0.5 to get to the centers. | |
| 116 fill_path.offset(SK_ScalarHalf, SK_ScalarHalf); | |
| 117 canvas_skia->drawPath(fill_path, fill); | |
| 118 | 117 |
| 119 SkPaint stroke; | 118 SkPaint stroke; |
| 120 stroke.setStyle(SkPaint::kStroke_Style); | 119 stroke.setStyle(SkPaint::kStroke_Style); |
| 121 const int kSeparatorThicknessPx = 1; | 120 const int kSeparatorThicknessPx = 1; |
| 122 stroke.setStrokeWidth(SkIntToScalar(kSeparatorThicknessPx)); | 121 stroke.setStrokeWidth(SkIntToScalar(kSeparatorThicknessPx)); |
| 123 stroke.setColor(separator_color); | 122 stroke.setColor(separator_color); |
| 124 stroke_path.transform(dsf_transform); | 123 stroke.setAntiAlias(true); |
| 125 stroke_path.offset(SK_ScalarHalf, SK_ScalarHalf); | 124 canvas->DrawPath(stroke_path, stroke); |
| 126 | 125 |
| 127 // The arrow part of the top separator. (The rest was drawn by the toolbar or | |
| 128 // the infobar above this one.) | |
| 129 stroke.setAntiAlias(true); | |
| 130 canvas_skia->drawPath(stroke_path, stroke); | |
| 131 // Bottom separator. | 126 // Bottom separator. |
| 132 stroke.setAntiAlias(false); | 127 stroke.setAntiAlias(false); |
| 128 gfx::SizeF view_size_px = gfx::ScaleSize(gfx::SizeF(view->size()), dsf); | |
| 133 SkScalar y = SkIntToScalar(view_size_px.height() - kSeparatorThicknessPx) + | 129 SkScalar y = SkIntToScalar(view_size_px.height() - kSeparatorThicknessPx) + |
| 134 SK_ScalarHalf; | 130 SK_ScalarHalf; |
| 135 SkScalar w = SkIntToScalar(view_size_px.width()); | 131 SkScalar w = SkFloatToScalar(view_size_px.width()); |
| 136 canvas_skia->drawLine(0, y, w, y, stroke); | 132 canvas->sk_canvas()->drawLine(0, y, w, y, stroke); |
| 137 } | 133 } |
| OLD | NEW |