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 3 // found in the LICENSE file. 4 5 #include "ui/views/controls/menu/menu_image_util.h" 6 7 #include "base/i18n/rtl.h" 8 #include "base/logging.h" 9 #include "grit/ui_resources.h" 10 #include "third_party/skia/include/effects/SkGradientShader.h" 11 #include "ui/base/resource/resource_bundle.h" 12 #include "ui/gfx/canvas.h" 13 #include "ui/gfx/image/canvas_image_source.h" 14 #include "ui/gfx/image/image.h" 15 #include "ui/gfx/image/image_skia.h" 16 #include "ui/gfx/image/image_skia_source.h" 17 #include "ui/gfx/point.h" 18 #include "ui/gfx/size.h" 19 20 namespace { 21 22 // Size of the radio button inciator. 23 const int kSelectedIndicatorSize = 5; 24 const int kIndicatorSize = 10; 25 26 // Used for the radio indicator. See theme_draw for details. 27 const double kGradientStop = .5; 28 const SkColor kGradient0 = SkColorSetRGB(255, 255, 255); 29 const SkColor kGradient1 = SkColorSetRGB(255, 255, 255); 30 const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8); 31 const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F); 32 const SkColor kRadioButtonIndicatorGradient0 = SkColorSetRGB(0, 0, 0); 33 const SkColor kRadioButtonIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83); 34 const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0); 35 36 class RadioButtonImageSource : public gfx::CanvasImageSource { 37 public: 38 explicit RadioButtonImageSource(bool selected) 39 : CanvasImageSource(gfx::Size(kIndicatorSize + 2, kIndicatorSize + 2), 40 false), 41 selected_(selected) { 42 } 43 virtual ~RadioButtonImageSource() {} 44 45 virtual void Draw(gfx::Canvas* canvas) OVERRIDE { 46 canvas->Translate(gfx::Vector2d(1, 1)); 47 48 SkPoint gradient_points[3]; 49 gradient_points[0].iset(0, 0); 50 gradient_points[1].iset(0, 51 static_cast<int>(kIndicatorSize * kGradientStop)); 52 gradient_points[2].iset(0, kIndicatorSize); 53 SkColor gradient_colors[3] = { kGradient0, kGradient1, kGradient2 }; 54 skia::RefPtr<SkShader> shader = skia::AdoptRef( 55 SkGradientShader::CreateLinear( 56 gradient_points, gradient_colors, NULL, arraysize(gradient_points), 57 SkShader::kClamp_TileMode, NULL)); 58 SkPaint paint; 59 paint.setStyle(SkPaint::kFill_Style); 60 paint.setAntiAlias(true); 61 paint.setShader(shader.get()); 62 int radius = kIndicatorSize / 2; 63 canvas->sk_canvas()->drawCircle(radius, radius, radius, paint); 64 paint.setStrokeWidth(SkIntToScalar(0)); 65 paint.setShader(NULL); 66 paint.setStyle(SkPaint::kStroke_Style); 67 paint.setColor(kBaseStroke); 68 canvas->sk_canvas()->drawCircle(radius, radius, radius, paint); 69 70 if (selected_) { 71 SkPoint selected_gradient_points[2]; 72 selected_gradient_points[0].iset(0, 0); 73 selected_gradient_points[1].iset(0, kSelectedIndicatorSize); 74 SkColor selected_gradient_colors[2] = { kRadioButtonIndicatorGradient0, 75 kRadioButtonIndicatorGradient1 }; 76 shader = skia::AdoptRef( 77 SkGradientShader::CreateLinear( 78 selected_gradient_points, selected_gradient_colors, NULL, 79 arraysize(selected_gradient_points), 80 SkShader::kClamp_TileMode, NULL)); 81 paint.setShader(shader.get()); 82 paint.setStyle(SkPaint::kFill_Style); 83 canvas->sk_canvas()->drawCircle(radius, radius, 84 kSelectedIndicatorSize / 2, paint); 85 86 paint.setStrokeWidth(SkIntToScalar(0)); 87 paint.setShader(NULL); 88 paint.setStyle(SkPaint::kStroke_Style); 89 paint.setColor(kIndicatorStroke); 90 canvas->sk_canvas()->drawCircle(radius, radius, 91 kSelectedIndicatorSize / 2, paint); 92 } 93 } 94 95 private: 96 bool selected_; 97 98 DISALLOW_COPY_AND_ASSIGN(RadioButtonImageSource); 99 }; 100 101 class SubmenuArrowImageSource : public gfx::CanvasImageSource { 102 public: 103 SubmenuArrowImageSource(int image_id) 104 : gfx::CanvasImageSource(ui::ResourceBundle::GetSharedInstance(). 105 GetImageNamed(image_id).ToImageSkia()->size(), false), 106 image_id_(image_id) {} 107 virtual ~SubmenuArrowImageSource() {} 108 109 virtual void Draw(gfx::Canvas* canvas) OVERRIDE { 110 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 111 const gfx::ImageSkia* r = rb.GetImageNamed(image_id_).ToImageSkia(); 112 canvas->Scale(-1, 1); 113 canvas->DrawImageInt(*r, - r->width(), 0); 114 } 115 116 private: 117 static gfx::Size GetSubmenuArrowSize() { 118 return ui::ResourceBundle::GetSharedInstance() 119 .GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia()->size(); 120 } 121 122 int image_id_; 123 124 DISALLOW_COPY_AND_ASSIGN(SubmenuArrowImageSource); 125 }; 126 127 gfx::ImageSkia GetRtlSubmenuArrowImage(bool rtl, 128 bool dark_background) { 129 int image_id = dark_background ? IDR_MENU_HIERARCHY_ARROW_DARK_BACKGROUND : 130 IDR_MENU_HIERARCHY_ARROW; 131 132 if (!rtl) { 133 return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id). 134 AsImageSkia(); 135 } 136 137 static gfx::ImageSkia* kRtlArrow = NULL; 138 static gfx::ImageSkia* kRtlArrowDarkBg = NULL; 139 gfx::ImageSkia** image = dark_background ? &kRtlArrowDarkBg : &kRtlArrow; 140 141 if (!*image) { 142 SubmenuArrowImageSource* source = new SubmenuArrowImageSource(image_id); 143 *image = new gfx::ImageSkia(source, source->size()); 144 } 145 146 return **image; 147 } 148 149 } // namespace 150 151 namespace views { 152 153 gfx::ImageSkia GetMenuCheckImage(bool dark_background) { 154 int image_id = dark_background ? IDR_MENU_CHECK_CHECKED_DARK_BACKGROUND : 155 IDR_MENU_CHECK_CHECKED; 156 return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id). 157 AsImageSkia(); 158 } 159 160 gfx::ImageSkia GetRadioButtonImage(bool selected) { 161 int image_id = selected ? IDR_MENU_RADIO_SELECTED : IDR_MENU_RADIO_EMPTY; 162 return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id). 163 AsImageSkia(); 164 } 165 166 gfx::ImageSkia GetSubmenuArrowImage(bool dark_background) { 167 return GetRtlSubmenuArrowImage(base::i18n::IsRTL(), dark_background); 168 } 169 170 } // namespace views 171