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
20namespace {
21
22// Size of the radio button inciator.
23const int kSelectedIndicatorSize = 5;
24const int kIndicatorSize = 10;
25
26// Used for the radio indicator. See theme_draw for details.
27const double kGradientStop = .5;
28const SkColor kGradient0 = SkColorSetRGB(255, 255, 255);
29const SkColor kGradient1 = SkColorSetRGB(255, 255, 255);
30const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8);
31const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F);
32const SkColor kRadioButtonIndicatorGradient0 = SkColorSetRGB(0, 0, 0);
33const SkColor kRadioButtonIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83);
34const SkColor kIndicatorStroke = SkColorSetRGB(0, 0, 0);
35
36class 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
101gfx::ImageSkia* CreateRadioButtonImage(bool selected) {
102  RadioButtonImageSource* source = new RadioButtonImageSource(selected);
103  return new gfx::ImageSkia(source, source->size());
104}
105
106class SubmenuArrowImageSource : public gfx::CanvasImageSource {
107 public:
108  SubmenuArrowImageSource()
109      : gfx::CanvasImageSource(GetSubmenuArrowSize(), false) {
110  }
111  virtual ~SubmenuArrowImageSource() {}
112
113  virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
114    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
115    const gfx::ImageSkia* r =
116        rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia();
117    canvas->Scale(-1, 1);
118    canvas->DrawImageInt(*r, - r->width(), 0);
119  }
120
121 private:
122  static gfx::Size GetSubmenuArrowSize() {
123    return ui::ResourceBundle::GetSharedInstance()
124        .GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia()->size();
125  }
126
127  DISALLOW_COPY_AND_ASSIGN(SubmenuArrowImageSource);
128};
129
130gfx::ImageSkia* GetRtlSubmenuArrowImage() {
131  static gfx::ImageSkia* kRtlArrow = NULL;
132  if (!kRtlArrow) {
133    SubmenuArrowImageSource* source = new SubmenuArrowImageSource();
134    kRtlArrow = new gfx::ImageSkia(source, source->size());
135  }
136  return kRtlArrow;
137}
138
139}  // namespace
140
141namespace views {
142
143const gfx::ImageSkia* GetMenuCheckImage() {
144  return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
145      IDR_MENU_CHECK_CHECKED).ToImageSkia();
146}
147
148const gfx::ImageSkia* GetRadioButtonImage(bool selected) {
149  int image_id = selected ? IDR_MENU_RADIO_SELECTED : IDR_MENU_RADIO_EMPTY;
150  return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
151      image_id).ToImageSkia();
152}
153
154const gfx::ImageSkia* GetSubmenuArrowImage() {
155  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
156  return base::i18n::IsRTL()
157      ? GetRtlSubmenuArrowImage()
158      : rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia();
159}
160
161}  // namespace views
162