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

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

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

Powered by Google App Engine
This is Rietveld 408576698