Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(386)

Side by Side Diff: ui/base/native_theme/native_theme_android.cc

Issue 10985076: NativeThemeAndroid should inherit from NativeThemeBase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/base/native_theme/native_theme_android.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "ui/base/native_theme/native_theme_android.h" 5 #include "ui/base/native_theme/native_theme_android.h"
6 6
7 #include <limits>
8
9 #include "base/basictypes.h" 7 #include "base/basictypes.h"
10 #include "base/logging.h" 8 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "grit/ui_resources.h"
13 #include "third_party/skia/include/effects/SkGradientShader.h"
14 #include "ui/base/layout.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/gfx/canvas.h"
17 #include "ui/gfx/color_utils.h"
18 #include "ui/gfx/rect.h"
19 #include "ui/gfx/size.h"
20 9
21 namespace ui { 10 namespace ui {
22 11
23 const unsigned int kButtonLength = 14;
24 const unsigned int kScrollbarWidth = 15;
25 const unsigned int kThumbInactiveColor = 0xeaeaea;
26 const unsigned int kTrackColor= 0xd3d3d3;
27
28 // These are the default dimensions of radio buttons and checkboxes.
29 const int kCheckboxAndRadioWidth = 13;
30 const int kCheckboxAndRadioHeight = 13;
31
32 // These sizes match the sizes in Chromium Win.
33 const int kSliderThumbWidth = 11;
34 const int kSliderThumbHeight = 21;
35
36 const SkColor kSliderTrackBackgroundColor = SkColorSetRGB(0xe3, 0xdd, 0xd8);
37 const SkColor kSliderThumbLightGrey = SkColorSetRGB(0xf4, 0xf2, 0xef);
38 const SkColor kSliderThumbDarkGrey = SkColorSetRGB(0xea, 0xe5, 0xe0);
39 const SkColor kSliderThumbBorderDarkGrey = SkColorSetRGB(0x9d, 0x96, 0x8e);
40
41 // Get lightness adjusted color.
42 SkColor BrightenColor(const color_utils::HSL& hsl,
43 SkAlpha alpha,
44 double lightness_amount) {
45 color_utils::HSL adjusted = hsl;
46 adjusted.l += lightness_amount;
47 if (adjusted.l > 1.0)
48 adjusted.l = 1.0;
49 if (adjusted.l < 0.0)
50 adjusted.l = 0.0;
51
52 return color_utils::HSLToSkColor(adjusted, alpha);
53 }
54
55 // static 12 // static
56 const NativeTheme* NativeTheme::instance() { 13 const NativeTheme* NativeTheme::instance() {
57 return NativeThemeAndroid::instance(); 14 return NativeThemeAndroid::instance();
58 } 15 }
59 16
60 // static 17 // static
61 const NativeThemeAndroid* NativeThemeAndroid::instance() { 18 const NativeThemeAndroid* NativeThemeAndroid::instance() {
62 CR_DEFINE_STATIC_LOCAL(NativeThemeAndroid, s_native_theme, ()); 19 CR_DEFINE_STATIC_LOCAL(NativeThemeAndroid, s_native_theme, ());
63 return &s_native_theme; 20 return &s_native_theme;
64 } 21 }
65 22
66 gfx::Size NativeThemeAndroid::GetPartSize(Part part,
67 State state,
68 const ExtraParams& extra) const {
69 switch (part) {
70 case kScrollbarDownArrow:
71 case kScrollbarUpArrow:
72 return gfx::Size(kScrollbarWidth, kButtonLength);
73 case kScrollbarLeftArrow:
74 case kScrollbarRightArrow:
75 return gfx::Size(kButtonLength, kScrollbarWidth);
76 case kCheckbox:
77 case kRadio:
78 return gfx::Size(kCheckboxAndRadioWidth, kCheckboxAndRadioHeight);
79 case kSliderThumb:
80 // These sizes match the sizes in Chromium Win.
81 return gfx::Size(kSliderThumbWidth, kSliderThumbHeight);
82 case kInnerSpinButton:
83 return gfx::Size(kScrollbarWidth, 0);
84 case kPushButton:
85 case kTextField:
86 case kMenuList:
87 case kSliderTrack:
88 case kProgressBar:
89 return gfx::Size(); // No default size.
90 default:
91 NOTREACHED();
92 }
93 return gfx::Size();
94 }
95
96 void NativeThemeAndroid::Paint(SkCanvas* canvas,
97 Part part,
98 State state,
99 const gfx::Rect& rect,
100 const ExtraParams& extra) const {
101 switch (part) {
102 case kScrollbarDownArrow:
103 case kScrollbarUpArrow:
104 case kScrollbarLeftArrow:
105 case kScrollbarRightArrow:
106 PaintArrowButton(canvas, rect, part, state);
107 break;
108 case kCheckbox:
109 PaintCheckbox(canvas, state, rect, extra.button);
110 break;
111 case kRadio:
112 PaintRadio(canvas, state, rect, extra.button);
113 break;
114 case kPushButton:
115 PaintButton(canvas, state, rect, extra.button);
116 break;
117 case kTextField:
118 PaintTextField(canvas, state, rect, extra.text_field);
119 break;
120 case kMenuList:
121 PaintMenuList(canvas, state, rect, extra.menu_list);
122 break;
123 case kSliderTrack:
124 PaintSliderTrack(canvas, state, rect, extra.slider);
125 break;
126 case kSliderThumb:
127 PaintSliderThumb(canvas, state, rect, extra.slider);
128 break;
129 case kInnerSpinButton:
130 PaintInnerSpinButton(canvas, state, rect, extra.inner_spin);
131 break;
132 case kProgressBar:
133 PaintProgressBar(canvas, state, rect, extra.progress_bar);
134 break;
135 default:
136 NOTREACHED();
137 }
138 }
139
140 SkColor NativeThemeAndroid::GetSystemColor(ColorId color_id) const { 23 SkColor NativeThemeAndroid::GetSystemColor(ColorId color_id) const {
141 NOTIMPLEMENTED(); 24 NOTIMPLEMENTED();
142 return SK_ColorBLACK; 25 return SK_ColorBLACK;
143 } 26 }
144 27
145 NativeThemeAndroid::NativeThemeAndroid() { 28 NativeThemeAndroid::NativeThemeAndroid() {
146 } 29 }
147 30
148 NativeThemeAndroid::~NativeThemeAndroid() { 31 NativeThemeAndroid::~NativeThemeAndroid() {
149 } 32 }
150 33
151 void NativeThemeAndroid::PaintArrowButton(SkCanvas* canvas,
152 const gfx::Rect& rect,
153 Part direction,
154 State state) const {
155 int widthMiddle;
156 int lengthMiddle;
157 SkPaint paint;
158 if (direction == kScrollbarUpArrow || direction == kScrollbarDownArrow) {
159 widthMiddle = rect.width() / 2 + 1;
160 lengthMiddle = rect.height() / 2 + 1;
161 } else {
162 lengthMiddle = rect.width() / 2 + 1;
163 widthMiddle = rect.height() / 2 + 1;
164 }
165
166 // Calculate button color.
167 SkScalar trackHSV[3];
168 SkColorToHSV(kTrackColor, trackHSV);
169 SkColor buttonColor = SaturateAndBrighten(trackHSV, 0, 0.2);
170 SkColor backgroundColor = buttonColor;
171 if (state == kPressed) {
172 SkScalar buttonHSV[3];
173 SkColorToHSV(buttonColor, buttonHSV);
174 buttonColor = SaturateAndBrighten(buttonHSV, 0, -0.1);
175 } else if (state == kHovered) {
176 SkScalar buttonHSV[3];
177 SkColorToHSV(buttonColor, buttonHSV);
178 buttonColor = SaturateAndBrighten(buttonHSV, 0, 0.05);
179 }
180
181 SkIRect skrect;
182 skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y()
183 + rect.height());
184 // Paint the background (the area visible behind the rounded corners).
185 paint.setColor(backgroundColor);
186 canvas->drawIRect(skrect, paint);
187
188 // Paint the button's outline and fill the middle
189 SkPath outline;
190 switch (direction) {
191 case kScrollbarUpArrow:
192 outline.moveTo(rect.x() + 0.5, rect.y() + rect.height() + 0.5);
193 outline.rLineTo(0, -(rect.height() - 2));
194 outline.rLineTo(2, -2);
195 outline.rLineTo(rect.width() - 5, 0);
196 outline.rLineTo(2, 2);
197 outline.rLineTo(0, rect.height() - 2);
198 break;
199 case kScrollbarDownArrow:
200 outline.moveTo(rect.x() + 0.5, rect.y() - 0.5);
201 outline.rLineTo(0, rect.height() - 2);
202 outline.rLineTo(2, 2);
203 outline.rLineTo(rect.width() - 5, 0);
204 outline.rLineTo(2, -2);
205 outline.rLineTo(0, -(rect.height() - 2));
206 break;
207 case kScrollbarRightArrow:
208 outline.moveTo(rect.x() - 0.5, rect.y() + 0.5);
209 outline.rLineTo(rect.width() - 2, 0);
210 outline.rLineTo(2, 2);
211 outline.rLineTo(0, rect.height() - 5);
212 outline.rLineTo(-2, 2);
213 outline.rLineTo(-(rect.width() - 2), 0);
214 break;
215 case kScrollbarLeftArrow:
216 outline.moveTo(rect.x() + rect.width() + 0.5, rect.y() + 0.5);
217 outline.rLineTo(-(rect.width() - 2), 0);
218 outline.rLineTo(-2, 2);
219 outline.rLineTo(0, rect.height() - 5);
220 outline.rLineTo(2, 2);
221 outline.rLineTo(rect.width() - 2, 0);
222 break;
223 default:
224 break;
225 }
226 outline.close();
227
228 paint.setStyle(SkPaint::kFill_Style);
229 paint.setColor(buttonColor);
230 canvas->drawPath(outline, paint);
231
232 paint.setAntiAlias(true);
233 paint.setStyle(SkPaint::kStroke_Style);
234 SkScalar thumbHSV[3];
235 SkColorToHSV(kThumbInactiveColor, thumbHSV);
236 paint.setColor(OutlineColor(trackHSV, thumbHSV));
237 canvas->drawPath(outline, paint);
238
239 // If the button is disabled or read-only, the arrow is drawn with the
240 // outline color.
241 if (state != kDisabled)
242 paint.setColor(SK_ColorBLACK);
243
244 paint.setAntiAlias(false);
245 paint.setStyle(SkPaint::kFill_Style);
246
247 SkPath path;
248 // The constants in this block of code are hand-tailored to produce good
249 // looking arrows without anti-aliasing.
250 switch (direction) {
251 case kScrollbarUpArrow:
252 path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle + 2);
253 path.rLineTo(7, 0);
254 path.rLineTo(-4, -4);
255 break;
256 case kScrollbarDownArrow:
257 path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle - 3);
258 path.rLineTo(7, 0);
259 path.rLineTo(-4, 4);
260 break;
261 case kScrollbarRightArrow:
262 path.moveTo(rect.x() + lengthMiddle - 3, rect.y() + widthMiddle - 4);
263 path.rLineTo(0, 7);
264 path.rLineTo(4, -4);
265 break;
266 case kScrollbarLeftArrow:
267 path.moveTo(rect.x() + lengthMiddle + 1, rect.y() + widthMiddle - 5);
268 path.rLineTo(0, 9);
269 path.rLineTo(-4, -4);
270 break;
271 default:
272 break;
273 }
274 path.close();
275
276 canvas->drawPath(path, paint);
277 }
278
279 void NativeThemeAndroid::PaintCheckbox(SkCanvas* canvas,
280 State state,
281 const gfx::Rect& rect,
282 const ButtonExtraParams& button) const {
283 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
284 gfx::ImageSkia* image = NULL;
285 if (button.indeterminate) {
286 image = state == kDisabled ?
287 rb.GetImageSkiaNamed(IDR_CHECKBOX_DISABLED_INDETERMINATE) :
288 rb.GetImageSkiaNamed(IDR_CHECKBOX_INDETERMINATE);
289 } else if (button.checked) {
290 image = state == kDisabled ?
291 rb.GetImageSkiaNamed(IDR_CHECKBOX_DISABLED_ON) :
292 rb.GetImageSkiaNamed(IDR_CHECKBOX_ON);
293 } else {
294 image = state == kDisabled ?
295 rb.GetImageSkiaNamed(IDR_CHECKBOX_DISABLED_OFF) :
296 rb.GetImageSkiaNamed(IDR_CHECKBOX_OFF);
297 }
298
299 gfx::Rect bounds = rect.Center(gfx::Size(image->width(), image->height()));
300 DrawImageInt(canvas, *image, 0, 0, image->width(), image->height(),
301 bounds.x(), bounds.y(), bounds.width(), bounds.height());
302 }
303
304 void NativeThemeAndroid::PaintRadio(SkCanvas* canvas,
305 State state,
306 const gfx::Rect& rect,
307 const ButtonExtraParams& button) const {
308 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
309 gfx::ImageSkia* image = NULL;
310 if (state == kDisabled) {
311 image = button.checked ?
312 rb.GetImageSkiaNamed(IDR_RADIO_DISABLED_ON) :
313 rb.GetImageSkiaNamed(IDR_RADIO_DISABLED_OFF);
314 } else {
315 image = button.checked ?
316 rb.GetImageSkiaNamed(IDR_RADIO_ON) :
317 rb.GetImageSkiaNamed(IDR_RADIO_OFF);
318 }
319
320 gfx::Rect bounds = rect.Center(gfx::Size(image->width(), image->height()));
321 DrawImageInt(canvas, *image, 0, 0, image->width(), image->height(),
322 bounds.x(), bounds.y(), bounds.width(), bounds.height());
323 }
324
325 void NativeThemeAndroid::PaintButton(SkCanvas* canvas,
326 State state,
327 const gfx::Rect& rect,
328 const ButtonExtraParams& button) const {
329 SkPaint paint;
330 SkRect skrect;
331 int kRight = rect.right();
332 int kBottom = rect.bottom();
333 SkColor base_color = button.background_color;
334
335 color_utils::HSL base_hsl;
336 color_utils::SkColorToHSL(base_color, &base_hsl);
337
338 // Our standard gradient is from 0xdd to 0xf8. This is the amount of
339 // increased luminance between those values.
340 SkColor light_color(BrightenColor(base_hsl, SkColorGetA(base_color), 0.105));
341
342 // If the button is too small, fallback to drawing a single, solid color
343 if (rect.width() < 5 || rect.height() < 5) {
344 paint.setColor(base_color);
345 skrect.set(rect.x(), rect.y(), kRight, kBottom);
346 canvas->drawRect(skrect, paint);
347 return;
348 }
349
350 if (button.has_border) {
351 int kBorderAlpha = state == kHovered ? 0x80 : 0x55;
352 paint.setARGB(kBorderAlpha, 0, 0, 0);
353 canvas->drawLine(rect.x() + 1, rect.y(), kRight - 1, rect.y(), paint);
354 canvas->drawLine(kRight - 1, rect.y() + 1, kRight - 1, kBottom - 1, paint);
355 canvas->drawLine(rect.x() + 1, kBottom - 1, kRight - 1, kBottom - 1, paint);
356 canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), kBottom - 1, paint);
357 }
358
359 paint.setColor(SK_ColorBLACK);
360 int kLightEnd = state == kPressed ? 1 : 0;
361 int kDarkEnd = !kLightEnd;
362 SkPoint gradient_bounds[2];
363 gradient_bounds[kLightEnd].iset(rect.x(), rect.y());
364 gradient_bounds[kDarkEnd].iset(rect.x(), kBottom - 1);
365 SkColor colors[2];
366 colors[0] = light_color;
367 colors[1] = base_color;
368
369 SkShader* shader = SkGradientShader::CreateLinear(
370 gradient_bounds, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
371 paint.setStyle(SkPaint::kFill_Style);
372 paint.setShader(shader);
373 shader->unref();
374
375 if (button.has_border) {
376 skrect.set(rect.x() + 1, rect.y() + 1, kRight - 1, kBottom - 1);
377 } else {
378 skrect.set(rect.x(), rect.y(), kRight, kBottom);
379 }
380 canvas->drawRect(skrect, paint);
381 paint.setShader(NULL);
382
383 if (button.has_border) {
384 paint.setColor(BrightenColor(base_hsl, SkColorGetA(base_color), -0.0588));
385 canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
386 canvas->drawPoint(kRight - 2, rect.y() + 1, paint);
387 canvas->drawPoint(rect.x() + 1, kBottom - 2, paint);
388 canvas->drawPoint(kRight - 2, kBottom - 2, paint);
389 }
390 }
391
392 void NativeThemeAndroid::PaintTextField(
393 SkCanvas* canvas,
394 State state,
395 const gfx::Rect& rect,
396 const TextFieldExtraParams& text) const {
397 // The following drawing code simulates the user-agent css border for
398 // text area and text input so that we do not break layout tests. Once we
399 // have decided the desired looks, we should update the code here and
400 // the layout test expectations.
401 SkRect bounds;
402 bounds.set(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1);
403
404 SkPaint fill_paint;
405 fill_paint.setStyle(SkPaint::kFill_Style);
406 fill_paint.setColor(text.background_color);
407 canvas->drawRect(bounds, fill_paint);
408
409 if (text.is_text_area) {
410 // Draw text area border: 1px solid black
411 SkPaint stroke_paint;
412 fill_paint.setStyle(SkPaint::kStroke_Style);
413 fill_paint.setColor(SK_ColorBLACK);
414 canvas->drawRect(bounds, fill_paint);
415 } else {
416 // Draw text input and listbox inset border
417 // Text Input: 2px inset #eee
418 // Listbox: 1px inset #808080
419 SkColor kLightColor = text.is_listbox ?
420 SkColorSetRGB(0x80, 0x80, 0x80) : SkColorSetRGB(0xee, 0xee, 0xee);
421 SkColor kDarkColor = text.is_listbox ?
422 SkColorSetRGB(0x2c, 0x2c, 0x2c) : SkColorSetRGB(0x9a, 0x9a, 0x9a);
423 int kBorderWidth = text.is_listbox ? 1 : 2;
424
425 SkPaint dark_paint;
426 dark_paint.setAntiAlias(true);
427 dark_paint.setStyle(SkPaint::kFill_Style);
428 dark_paint.setColor(kDarkColor);
429
430 SkPaint light_paint;
431 light_paint.setAntiAlias(true);
432 light_paint.setStyle(SkPaint::kFill_Style);
433 light_paint.setColor(kLightColor);
434
435 int left = rect.x();
436 int top = rect.y();
437 int right = rect.right();
438 int bottom = rect.bottom();
439
440 SkPath path;
441 path.incReserve(4);
442
443 // Top
444 path.moveTo(SkIntToScalar(left), SkIntToScalar(top));
445 path.lineTo(SkIntToScalar(left + kBorderWidth),
446 SkIntToScalar(top + kBorderWidth));
447 path.lineTo(SkIntToScalar(right - kBorderWidth),
448 SkIntToScalar(top + kBorderWidth));
449 path.lineTo(SkIntToScalar(right), SkIntToScalar(top));
450 canvas->drawPath(path, dark_paint);
451
452 // Bottom
453 path.reset();
454 path.moveTo(SkIntToScalar(left + kBorderWidth),
455 SkIntToScalar(bottom - kBorderWidth));
456 path.lineTo(SkIntToScalar(left), SkIntToScalar(bottom));
457 path.lineTo(SkIntToScalar(right), SkIntToScalar(bottom));
458 path.lineTo(SkIntToScalar(right - kBorderWidth),
459 SkIntToScalar(bottom - kBorderWidth));
460 canvas->drawPath(path, light_paint);
461
462 // Left
463 path.reset();
464 path.moveTo(SkIntToScalar(left), SkIntToScalar(top));
465 path.lineTo(SkIntToScalar(left), SkIntToScalar(bottom));
466 path.lineTo(SkIntToScalar(left + kBorderWidth),
467 SkIntToScalar(bottom - kBorderWidth));
468 path.lineTo(SkIntToScalar(left + kBorderWidth),
469 SkIntToScalar(top + kBorderWidth));
470 canvas->drawPath(path, dark_paint);
471
472 // Right
473 path.reset();
474 path.moveTo(SkIntToScalar(right - kBorderWidth),
475 SkIntToScalar(top + kBorderWidth));
476 path.lineTo(SkIntToScalar(right - kBorderWidth), SkIntToScalar(bottom));
477 path.lineTo(SkIntToScalar(right), SkIntToScalar(bottom));
478 path.lineTo(SkIntToScalar(right), SkIntToScalar(top));
479 canvas->drawPath(path, light_paint);
480 }
481 }
482
483 void NativeThemeAndroid::PaintMenuList(
484 SkCanvas* canvas,
485 State state,
486 const gfx::Rect& rect,
487 const MenuListExtraParams& menu_list) const {
488 // If a border radius is specified, we let the WebCore paint the background
489 // and the border of the control.
490 if (!menu_list.has_border_radius) {
491 ButtonExtraParams button = { 0 };
492 button.background_color = menu_list.background_color;
493 button.has_border = menu_list.has_border;
494 PaintButton(canvas, state, rect, button);
495 }
496
497 SkPaint paint;
498 paint.setColor(SK_ColorBLACK);
499 paint.setAntiAlias(true);
500 paint.setStyle(SkPaint::kFill_Style);
501
502 SkPath path;
503 path.moveTo(menu_list.arrow_x, menu_list.arrow_y - 3);
504 path.rLineTo(6, 0);
505 path.rLineTo(-3, 6);
506 path.close();
507 canvas->drawPath(path, paint);
508 }
509
510 void NativeThemeAndroid::PaintSliderTrack(
511 SkCanvas* canvas,
512 State state,
513 const gfx::Rect& rect,
514 const SliderExtraParams& slider) const {
515 int kMidX = rect.x() + rect.width() / 2;
516 int kMidY = rect.y() + rect.height() / 2;
517
518 SkPaint paint;
519 paint.setColor(kSliderTrackBackgroundColor);
520
521 SkRect skrect;
522 if (slider.vertical) {
523 skrect.set(std::max(rect.x(), kMidX - 2),
524 rect.y(),
525 std::min(rect.right(), kMidX + 2),
526 rect.bottom());
527 } else {
528 skrect.set(rect.x(),
529 std::max(rect.y(), kMidY - 2),
530 rect.right(),
531 std::min(rect.bottom(), kMidY + 2));
532 }
533 canvas->drawRect(skrect, paint);
534 }
535
536 void NativeThemeAndroid::PaintSliderThumb(
537 SkCanvas* canvas,
538 State state,
539 const gfx::Rect& rect,
540 const SliderExtraParams& slider) const {
541 bool hovered = (state == kHovered) || slider.in_drag;
542 int kMidX = rect.x() + rect.width() / 2;
543 int kMidY = rect.y() + rect.height() / 2;
544
545 SkPaint paint;
546 paint.setColor(hovered ? SK_ColorWHITE : kSliderThumbLightGrey);
547
548 SkIRect skrect;
549 if (slider.vertical)
550 skrect.set(rect.x(), rect.y(), kMidX + 1, rect.bottom());
551 else
552 skrect.set(rect.x(), rect.y(), rect.right(), kMidY + 1);
553
554 canvas->drawIRect(skrect, paint);
555
556 paint.setColor(hovered ? kSliderThumbLightGrey : kSliderThumbDarkGrey);
557
558 if (slider.vertical)
559 skrect.set(kMidX + 1, rect.y(), rect.right(), rect.bottom());
560 else
561 skrect.set(rect.x(), kMidY + 1, rect.right(), rect.bottom());
562
563 canvas->drawIRect(skrect, paint);
564
565 paint.setColor(kSliderThumbBorderDarkGrey);
566 DrawBox(canvas, rect, paint);
567
568 if (rect.height() > 10 && rect.width() > 10) {
569 DrawHorizLine(canvas, kMidX - 2, kMidX + 2, kMidY, paint);
570 DrawHorizLine(canvas, kMidX - 2, kMidX + 2, kMidY - 3, paint);
571 DrawHorizLine(canvas, kMidX - 2, kMidX + 2, kMidY + 3, paint);
572 }
573 }
574
575 void NativeThemeAndroid::PaintInnerSpinButton(
576 SkCanvas* canvas,
577 State state,
578 const gfx::Rect& rect,
579 const InnerSpinButtonExtraParams& spin_button) const {
580 if (spin_button.read_only)
581 state = kDisabled;
582
583 State north_state = state;
584 State south_state = state;
585 if (spin_button.spin_up)
586 south_state = south_state != kDisabled ? kNormal : kDisabled;
587 else
588 north_state = north_state != kDisabled ? kNormal : kDisabled;
589
590 gfx::Rect half = rect;
591 half.set_height(rect.height() / 2);
592 PaintArrowButton(canvas, half, kScrollbarUpArrow, north_state);
593
594 half.set_y(rect.y() + rect.height() / 2);
595 PaintArrowButton(canvas, half, kScrollbarDownArrow, south_state);
596 }
597
598 void NativeThemeAndroid::PaintProgressBar(
599 SkCanvas* canvas,
600 State state,
601 const gfx::Rect& rect,
602 const ProgressBarExtraParams& progress_bar) const {
603 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
604 gfx::ImageSkia* bar_image = rb.GetImageSkiaNamed(IDR_PROGRESS_BAR);
605 gfx::ImageSkia* left_border_image = rb.GetImageSkiaNamed(
606 IDR_PROGRESS_BORDER_LEFT);
607 gfx::ImageSkia* right_border_image = rb.GetImageSkiaNamed(
608 IDR_PROGRESS_BORDER_RIGHT);
609
610 float tile_scale = static_cast<float>(rect.height()) /
611 bar_image->height();
612
613 int new_tile_width = static_cast<int>(bar_image->width() * tile_scale);
614 float tile_scale_x = static_cast<float>(new_tile_width) /
615 bar_image->width();
616
617 DrawTiledImage(canvas, *bar_image, 0, 0, tile_scale_x, tile_scale,
618 rect.x(), rect.y(), rect.width(), rect.height());
619
620 if (progress_bar.value_rect_width) {
621 gfx::ImageSkia* value_image = rb.GetImageSkiaNamed(IDR_PROGRESS_VALUE);
622
623 new_tile_width = static_cast<int>(value_image->width() * tile_scale);
624 tile_scale_x = static_cast<float>(new_tile_width) /
625 value_image->width();
626
627 DrawTiledImage(canvas, *value_image, 0, 0, tile_scale_x, tile_scale,
628 progress_bar.value_rect_x,
629 progress_bar.value_rect_y,
630 progress_bar.value_rect_width,
631 progress_bar.value_rect_height);
632 }
633
634 int dest_left_border_width = static_cast<int>(left_border_image->width() *
635 tile_scale);
636 DrawImageInt(canvas, *left_border_image, 0, 0, left_border_image->width(),
637 left_border_image->height(), rect.x(), rect.y(), dest_left_border_width,
638 rect.height());
639
640 int dest_right_border_width = static_cast<int>(right_border_image->width() *
641 tile_scale);
642 int dest_x = rect.right() - dest_right_border_width;
643 DrawImageInt(canvas, *right_border_image, 0, 0, right_border_image->width(),
644 right_border_image->height(), dest_x, rect.y(), dest_right_border_width,
645 rect.height());
646 }
647
648 bool NativeThemeAndroid::IntersectsClipRectInt(SkCanvas* canvas,
649 int x,
650 int y,
651 int w,
652 int h) const {
653 SkRect clip;
654 return canvas->getClipBounds(&clip) &&
655 clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
656 SkIntToScalar(y + h));
657 }
658
659 void NativeThemeAndroid::DrawImageInt(SkCanvas* sk_canvas,
660 const gfx::ImageSkia& image,
661 int src_x,
662 int src_y,
663 int src_w,
664 int src_h,
665 int dest_x,
666 int dest_y,
667 int dest_w,
668 int dest_h) const {
669 // TODO(pkotwicz): Do something better and don't infer device
670 // scale factor from canvas scale.
671 SkMatrix m = sk_canvas->getTotalMatrix();
672 ui::ScaleFactor device_scale_factor = ui::GetScaleFactorFromScale(
673 SkScalarAbs(m.getScaleX()));
674 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
675 sk_canvas, device_scale_factor));
676 canvas->DrawImageInt(image, src_x, src_y, src_w, src_h,
677 dest_x, dest_y, dest_w, dest_h, true);
678 }
679
680 void NativeThemeAndroid::DrawTiledImage(SkCanvas* sk_canvas,
681 const gfx::ImageSkia& image,
682 int src_x,
683 int src_y,
684 float tile_scale_x,
685 float tile_scale_y,
686 int dest_x,
687 int dest_y,
688 int w,
689 int h) const {
690 // TODO(pkotwicz): Do something better and don't infer device
691 // scale factor from canvas scale.
692 SkMatrix m = sk_canvas->getTotalMatrix();
693 ui::ScaleFactor device_scale_factor = ui::GetScaleFactorFromScale(
694 SkScalarAbs(m.getScaleX()));
695 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling(
696 sk_canvas, device_scale_factor));
697 canvas->TileImageInt(image, src_x, src_y, tile_scale_x,
698 tile_scale_y, dest_x, dest_y, w, h);
699 }
700
701 SkColor NativeThemeAndroid::SaturateAndBrighten(
702 SkScalar* hsv,
703 SkScalar saturate_amount,
704 SkScalar brighten_amount) const {
705 SkScalar color[3];
706 color[0] = hsv[0];
707 color[1] = Clamp(hsv[1] + saturate_amount, 0.0, 1.0);
708 color[2] = Clamp(hsv[2] + brighten_amount, 0.0, 1.0);
709 return SkHSVToColor(color);
710 }
711
712 SkScalar NativeThemeAndroid::Clamp(SkScalar value,
713 SkScalar min,
714 SkScalar max) const {
715 return std::min(std::max(value, min), max);
716 }
717
718 void NativeThemeAndroid::DrawVertLine(SkCanvas* canvas,
719 int x,
720 int y1,
721 int y2,
722 const SkPaint& paint) const {
723 SkIRect skrect;
724 skrect.set(x, y1, x + 1, y2 + 1);
725 canvas->drawIRect(skrect, paint);
726 }
727
728 void NativeThemeAndroid::DrawHorizLine(SkCanvas* canvas,
729 int x1,
730 int x2,
731 int y,
732 const SkPaint& paint) const {
733 SkIRect skrect;
734 skrect.set(x1, y, x2 + 1, y + 1);
735 canvas->drawIRect(skrect, paint);
736 }
737
738 void NativeThemeAndroid::DrawBox(SkCanvas* canvas,
739 const gfx::Rect& rect,
740 const SkPaint& paint) const {
741 int right = rect.x() + rect.width() - 1;
742 int bottom = rect.y() + rect.height() - 1;
743 DrawHorizLine(canvas, rect.x(), right, rect.y(), paint);
744 DrawVertLine(canvas, right, rect.y(), bottom, paint);
745 DrawHorizLine(canvas, rect.x(), right, bottom, paint);
746 DrawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
747 }
748
749 SkColor NativeThemeAndroid::OutlineColor(SkScalar* hsv1, SkScalar* hsv2) const {
750 SkScalar min_diff = Clamp((hsv1[1] + hsv2[1]) * 1.2, 0.28, 0.5);
751 SkScalar diff = Clamp(fabs(hsv1[2] - hsv2[2]) / 2, min_diff, 0.5);
752
753 if (hsv1[2] + hsv2[2] > 1.0)
754 diff = -diff;
755
756 return SaturateAndBrighten(hsv2, -0.2, diff);
757 }
758
759 } // namespace ui 34 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/native_theme/native_theme_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698