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

Side by Side Diff: components/test_runner/mock_web_theme_engine.cc

Issue 2707183003: Move //components/test_runner back into //content/shell (Closed)
Patch Set: Trim DEPS Created 3 years, 10 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
OLDNEW
(Empty)
1 // Copyright 2014 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 "components/test_runner/mock_web_theme_engine.h"
6
7 #if !defined(OS_MACOSX)
8
9 #include "base/logging.h"
10 #include "build/build_config.h"
11 #include "cc/paint/paint_canvas.h"
12 #include "cc/paint/paint_flags.h"
13 #include "third_party/WebKit/public/platform/WebRect.h"
14 #include "third_party/WebKit/public/platform/WebSize.h"
15 #include "third_party/skia/include/core/SkPaint.h"
16 #include "third_party/skia/include/core/SkPath.h"
17 #include "third_party/skia/include/core/SkRect.h"
18
19 using blink::WebCanvas;
20 using blink::WebColor;
21 using blink::WebRect;
22 using blink::WebThemeEngine;
23
24 namespace test_runner {
25
26 namespace {
27
28 const SkColor edgeColor = SK_ColorBLACK;
29 const SkColor readOnlyColor = SkColorSetRGB(0xe9, 0xc2, 0xa6);
30
31 } // namespace
32
33 SkColor bgColors(WebThemeEngine::State state) {
34 switch (state) {
35 case WebThemeEngine::StateDisabled:
36 return SkColorSetRGB(0xc9, 0xc9, 0xc9);
37 case WebThemeEngine::StateHover:
38 return SkColorSetRGB(0x43, 0xf9, 0xff);
39 case WebThemeEngine::StateNormal:
40 return SkColorSetRGB(0x89, 0xc4, 0xff);
41 case WebThemeEngine::StatePressed:
42 return SkColorSetRGB(0xa9, 0xff, 0x12);
43 case WebThemeEngine::StateFocused:
44 return SkColorSetRGB(0x00, 0xf3, 0xac);
45 case WebThemeEngine::StateReadonly:
46 return SkColorSetRGB(0xf3, 0xe0, 0xd0);
47 default:
48 NOTREACHED();
49 }
50 return SkColorSetRGB(0x00, 0x00, 0xff);
51 }
52
53 blink::WebSize MockWebThemeEngine::getSize(WebThemeEngine::Part part) {
54 // FIXME: We use this constant to indicate we are being asked for the size of
55 // a part that we don't expect to be asked about. We return a garbage value
56 // rather than just asserting because this code doesn't have access to either
57 // WTF or base to raise an assertion or do any logging :(.
58 const blink::WebSize invalidPartSize = blink::WebSize(100, 100);
59
60 switch (part) {
61 case WebThemeEngine::PartScrollbarLeftArrow:
62 return blink::WebSize(17, 15);
63 case WebThemeEngine::PartScrollbarRightArrow:
64 return invalidPartSize;
65 case WebThemeEngine::PartScrollbarUpArrow:
66 return blink::WebSize(15, 17);
67 case WebThemeEngine::PartScrollbarDownArrow:
68 return invalidPartSize;
69 case WebThemeEngine::PartScrollbarHorizontalThumb:
70 return blink::WebSize(15, 15);
71 case WebThemeEngine::PartScrollbarVerticalThumb:
72 return blink::WebSize(15, 15);
73 case WebThemeEngine::PartScrollbarHorizontalTrack:
74 return blink::WebSize(0, 15);
75 case WebThemeEngine::PartScrollbarVerticalTrack:
76 return blink::WebSize(15, 0);
77 case WebThemeEngine::PartCheckbox:
78 case WebThemeEngine::PartRadio:
79 return blink::WebSize(13, 13);
80 case WebThemeEngine::PartSliderThumb:
81 return blink::WebSize(11, 21);
82 case WebThemeEngine::PartInnerSpinButton:
83 return blink::WebSize(15, 8);
84 default:
85 return invalidPartSize;
86 }
87 }
88
89 static SkIRect webRectToSkIRect(const WebRect& webRect) {
90 SkIRect irect;
91 irect.set(webRect.x, webRect.y, webRect.x + webRect.width - 1,
92 webRect.y + webRect.height - 1);
93 return irect;
94 }
95
96 static SkIRect validate(const SkIRect& rect, WebThemeEngine::Part part) {
97 switch (part) {
98 case WebThemeEngine::PartCheckbox:
99 case WebThemeEngine::PartRadio: {
100 SkIRect retval = rect;
101
102 // The maximum width and height is 13.
103 // Center the square in the passed rectangle.
104 const int maxControlSize = 13;
105 int controlSize = std::min(rect.width(), rect.height());
106 controlSize = std::min(controlSize, maxControlSize);
107
108 retval.fLeft = rect.fLeft + (rect.width() / 2) - (controlSize / 2);
109 retval.fRight = retval.fLeft + controlSize - 1;
110 retval.fTop = rect.fTop + (rect.height() / 2) - (controlSize / 2);
111 retval.fBottom = retval.fTop + controlSize - 1;
112
113 return retval;
114 }
115 default:
116 return rect;
117 }
118 }
119
120 void box(cc::PaintCanvas* canvas, const SkIRect& rect, SkColor fillColor) {
121 cc::PaintFlags flags;
122
123 flags.setStyle(cc::PaintFlags::kFill_Style);
124 flags.setColor(fillColor);
125 canvas->drawIRect(rect, flags);
126
127 flags.setColor(edgeColor);
128 flags.setStyle(cc::PaintFlags::kStroke_Style);
129 canvas->drawIRect(rect, flags);
130 }
131
132 void line(cc::PaintCanvas* canvas,
133 int x0,
134 int y0,
135 int x1,
136 int y1,
137 SkColor color) {
138 cc::PaintFlags flags;
139 flags.setColor(color);
140 canvas->drawLine(SkIntToScalar(x0), SkIntToScalar(y0), SkIntToScalar(x1),
141 SkIntToScalar(y1), flags);
142 }
143
144 void triangle(cc::PaintCanvas* canvas,
145 int x0,
146 int y0,
147 int x1,
148 int y1,
149 int x2,
150 int y2,
151 SkColor color) {
152 SkPath path;
153 cc::PaintFlags flags;
154
155 flags.setColor(color);
156 flags.setStyle(cc::PaintFlags::kFill_Style);
157 path.incReserve(4);
158 path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0));
159 path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1));
160 path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2));
161 path.close();
162 canvas->drawPath(path, flags);
163
164 flags.setColor(edgeColor);
165 flags.setStyle(cc::PaintFlags::kStroke_Style);
166 canvas->drawPath(path, flags);
167 }
168
169 void roundRect(cc::PaintCanvas* canvas, SkIRect irect, SkColor color) {
170 SkRect rect;
171 SkScalar radius = SkIntToScalar(5);
172 cc::PaintFlags flags;
173
174 rect.set(irect);
175 flags.setColor(color);
176 flags.setStyle(cc::PaintFlags::kFill_Style);
177 canvas->drawRoundRect(rect, radius, radius, flags);
178
179 flags.setColor(edgeColor);
180 flags.setStyle(cc::PaintFlags::kStroke_Style);
181 canvas->drawRoundRect(rect, radius, radius, flags);
182 }
183
184 void oval(cc::PaintCanvas* canvas, SkIRect irect, SkColor color) {
185 SkRect rect;
186 cc::PaintFlags flags;
187
188 rect.set(irect);
189 flags.setColor(color);
190 flags.setStyle(cc::PaintFlags::kFill_Style);
191 canvas->drawOval(rect, flags);
192
193 flags.setColor(edgeColor);
194 flags.setStyle(cc::PaintFlags::kStroke_Style);
195 canvas->drawOval(rect, flags);
196 }
197
198 void circle(cc::PaintCanvas* canvas,
199 SkIRect irect,
200 SkScalar radius,
201 SkColor color) {
202 int left = irect.fLeft;
203 int width = irect.width();
204 int height = irect.height();
205 int top = irect.fTop;
206
207 SkScalar cy = SkIntToScalar(top + height / 2);
208 SkScalar cx = SkIntToScalar(left + width / 2);
209 cc::PaintFlags flags;
210
211 flags.setColor(color);
212 flags.setStyle(cc::PaintFlags::kFill_Style);
213 canvas->drawCircle(cx, cy, radius, flags);
214
215 flags.setColor(edgeColor);
216 flags.setStyle(cc::PaintFlags::kStroke_Style);
217 canvas->drawCircle(cx, cy, radius, flags);
218 }
219
220 void nestedBoxes(cc::PaintCanvas* canvas,
221 SkIRect irect,
222 int indentLeft,
223 int indentTop,
224 int indentRight,
225 int indentBottom,
226 SkColor outerColor,
227 SkColor innerColor) {
228 SkIRect lirect;
229 box(canvas, irect, outerColor);
230 lirect.set(irect.fLeft + indentLeft, irect.fTop + indentTop,
231 irect.fRight - indentRight, irect.fBottom - indentBottom);
232 box(canvas, lirect, innerColor);
233 }
234
235 void insetBox(cc::PaintCanvas* canvas,
236 SkIRect irect,
237 int indentLeft,
238 int indentTop,
239 int indentRight,
240 int indentBottom,
241 SkColor color) {
242 SkIRect lirect;
243 lirect.set(irect.fLeft + indentLeft, irect.fTop + indentTop,
244 irect.fRight - indentRight, irect.fBottom - indentBottom);
245 box(canvas, lirect, color);
246 }
247
248 void markState(cc::PaintCanvas* canvas,
249 SkIRect irect,
250 WebThemeEngine::State state) {
251 int left = irect.fLeft;
252 int right = irect.fRight;
253 int top = irect.fTop;
254 int bottom = irect.fBottom;
255
256 // The length of a triangle side for the corner marks.
257 const int triangleSize = 5;
258
259 switch (state) {
260 case WebThemeEngine::StateDisabled:
261 case WebThemeEngine::StateNormal:
262 // Don't visually mark these states (color is enough).
263 break;
264
265 case WebThemeEngine::StateReadonly: {
266 // The horizontal lines in a read only control are spaced by this amount.
267 const int readOnlyLineOffset = 5;
268
269 // Drawing lines across the control.
270 for (int i = top + readOnlyLineOffset; i < bottom;
271 i += readOnlyLineOffset)
272 line(canvas, left + 1, i, right - 1, i, readOnlyColor);
273 break;
274 }
275 case WebThemeEngine::StateHover:
276 // Draw a triangle in the upper left corner of the control. (Win's "hot")
277 triangle(canvas, left, top, left + triangleSize, top, left,
278 top + triangleSize, edgeColor);
279 break;
280
281 case WebThemeEngine::StateFocused:
282 // Draw a triangle in the bottom right corner of the control.
283 triangle(canvas, right, bottom, right - triangleSize, bottom, right,
284 bottom - triangleSize, edgeColor);
285 break;
286
287 case WebThemeEngine::StatePressed:
288 // Draw a triangle in the bottom left corner of the control.
289 triangle(canvas, left, bottom, left, bottom - triangleSize,
290 left + triangleSize, bottom, edgeColor);
291 break;
292
293 default:
294 // FIXME: Should we do something here to indicate that we got an invalid
295 // state?
296 // Unfortunately, we can't assert because we don't have access to WTF or
297 // base.
298 break;
299 }
300 }
301
302 void MockWebThemeEngine::paint(blink::WebCanvas* canvas,
303 WebThemeEngine::Part part,
304 WebThemeEngine::State state,
305 const blink::WebRect& rect,
306 const WebThemeEngine::ExtraParams* extraParams) {
307 SkIRect irect = webRectToSkIRect(rect);
308 cc::PaintFlags flags;
309
310 // Indent amounts for the check in a checkbox or radio button.
311 const int checkIndent = 3;
312
313 // Indent amounts for short and long sides of the scrollbar notches.
314 const int notchLongOffset = 1;
315 const int notchShortOffset = 4;
316 const int noOffset = 0;
317
318 // Indent amounts for the short and long sides of a scroll thumb box.
319 const int thumbLongIndent = 0;
320 const int thumbShortIndent = 2;
321
322 // Indents for the crosshatch on a scroll grip.
323 const int gripLongIndent = 3;
324 const int gripShortIndent = 5;
325
326 // Indents for the the slider track.
327 const int sliderIndent = 2;
328
329 int halfHeight = irect.height() / 2;
330 int halfWidth = irect.width() / 2;
331 int quarterHeight = irect.height() / 4;
332 int quarterWidth = irect.width() / 4;
333 int left = irect.fLeft;
334 int right = irect.fRight;
335 int top = irect.fTop;
336 int bottom = irect.fBottom;
337
338 switch (part) {
339 case WebThemeEngine::PartScrollbarDownArrow:
340 box(canvas, irect, bgColors(state));
341 triangle(canvas, left + quarterWidth, top + quarterHeight,
342 right - quarterWidth, top + quarterHeight, left + halfWidth,
343 bottom - quarterHeight, edgeColor);
344 markState(canvas, irect, state);
345 break;
346
347 case WebThemeEngine::PartScrollbarLeftArrow:
348 box(canvas, irect, bgColors(state));
349 triangle(canvas, right - quarterWidth, top + quarterHeight,
350 right - quarterWidth, bottom - quarterHeight,
351 left + quarterWidth, top + halfHeight, edgeColor);
352 break;
353
354 case WebThemeEngine::PartScrollbarRightArrow:
355 box(canvas, irect, bgColors(state));
356 triangle(canvas, left + quarterWidth, top + quarterHeight,
357 right - quarterWidth, top + halfHeight, left + quarterWidth,
358 bottom - quarterHeight, edgeColor);
359 break;
360
361 case WebThemeEngine::PartScrollbarUpArrow:
362 box(canvas, irect, bgColors(state));
363 triangle(canvas, left + quarterWidth, bottom - quarterHeight,
364 left + halfWidth, top + quarterHeight, right - quarterWidth,
365 bottom - quarterHeight, edgeColor);
366 markState(canvas, irect, state);
367 break;
368
369 case WebThemeEngine::PartScrollbarHorizontalThumb: {
370 // Draw a narrower box on top of the outside box.
371 nestedBoxes(canvas, irect, thumbLongIndent, thumbShortIndent,
372 thumbLongIndent, thumbShortIndent, bgColors(state),
373 bgColors(state));
374 // Draw a horizontal crosshatch for the grip.
375 int longOffset = halfWidth - gripLongIndent;
376 line(canvas, left + gripLongIndent, top + halfHeight,
377 right - gripLongIndent, top + halfHeight, edgeColor);
378 line(canvas, left + longOffset, top + gripShortIndent, left + longOffset,
379 bottom - gripShortIndent, edgeColor);
380 line(canvas, right - longOffset, top + gripShortIndent,
381 right - longOffset, bottom - gripShortIndent, edgeColor);
382 markState(canvas, irect, state);
383 break;
384 }
385
386 case WebThemeEngine::PartScrollbarVerticalThumb: {
387 // Draw a shorter box on top of the outside box.
388 nestedBoxes(canvas, irect, thumbShortIndent, thumbLongIndent,
389 thumbShortIndent, thumbLongIndent, bgColors(state),
390 bgColors(state));
391 // Draw a vertical crosshatch for the grip.
392 int longOffset = halfHeight - gripLongIndent;
393 line(canvas, left + halfWidth, top + gripLongIndent, left + halfWidth,
394 bottom - gripLongIndent, edgeColor);
395 line(canvas, left + gripShortIndent, top + longOffset,
396 right - gripShortIndent, top + longOffset, edgeColor);
397 line(canvas, left + gripShortIndent, bottom - longOffset,
398 right - gripShortIndent, bottom - longOffset, edgeColor);
399 markState(canvas, irect, state);
400 break;
401 }
402
403 case WebThemeEngine::PartScrollbarHorizontalTrack: {
404 int longOffset = halfHeight - notchLongOffset;
405 int shortOffset = irect.width() - notchShortOffset;
406 box(canvas, irect, bgColors(state));
407 // back, notch on right
408 insetBox(canvas, irect, noOffset, longOffset, shortOffset, longOffset,
409 edgeColor);
410 // forward, notch on right
411 insetBox(canvas, irect, shortOffset, longOffset, noOffset, longOffset,
412 edgeColor);
413 markState(canvas, irect, state);
414 break;
415 }
416
417 case WebThemeEngine::PartScrollbarVerticalTrack: {
418 int longOffset = halfWidth - notchLongOffset;
419 int shortOffset = irect.height() - notchShortOffset;
420 box(canvas, irect, bgColors(state));
421 // back, notch at top
422 insetBox(canvas, irect, longOffset, noOffset, longOffset, shortOffset,
423 edgeColor);
424 // forward, notch at bottom
425 insetBox(canvas, irect, longOffset, shortOffset, longOffset, noOffset,
426 edgeColor);
427 markState(canvas, irect, state);
428 break;
429 }
430
431 case WebThemeEngine::PartScrollbarCorner: {
432 SkIRect cornerRect = {rect.x, rect.y, rect.x + rect.width,
433 rect.y + rect.height};
434 flags.setColor(SK_ColorWHITE);
435 flags.setStyle(cc::PaintFlags::kFill_Style);
436 flags.setBlendMode(SkBlendMode::kSrc);
437 flags.setAntiAlias(true);
438 canvas->drawIRect(cornerRect, flags);
439 break;
440 }
441
442 case WebThemeEngine::PartCheckbox:
443 if (extraParams->button.indeterminate) {
444 nestedBoxes(canvas, irect, checkIndent, halfHeight, checkIndent,
445 halfHeight, bgColors(state), edgeColor);
446 } else if (extraParams->button.checked) {
447 irect = validate(irect, part);
448 nestedBoxes(canvas, irect, checkIndent, checkIndent, checkIndent,
449 checkIndent, bgColors(state), edgeColor);
450 } else {
451 irect = validate(irect, part);
452 box(canvas, irect, bgColors(state));
453 }
454 break;
455
456 case WebThemeEngine::PartRadio:
457 irect = validate(irect, part);
458 halfHeight = irect.height() / 2;
459 if (extraParams->button.checked) {
460 circle(canvas, irect, SkIntToScalar(halfHeight), bgColors(state));
461 circle(canvas, irect, SkIntToScalar(halfHeight - checkIndent),
462 edgeColor);
463 } else {
464 circle(canvas, irect, SkIntToScalar(halfHeight), bgColors(state));
465 }
466 break;
467
468 case WebThemeEngine::PartButton:
469 roundRect(canvas, irect, bgColors(state));
470 markState(canvas, irect, state);
471 break;
472
473 case WebThemeEngine::PartTextField:
474 flags.setColor(extraParams->textField.backgroundColor);
475 flags.setStyle(cc::PaintFlags::kFill_Style);
476 canvas->drawIRect(irect, flags);
477
478 flags.setColor(edgeColor);
479 flags.setStyle(cc::PaintFlags::kStroke_Style);
480 canvas->drawIRect(irect, flags);
481
482 markState(canvas, irect, state);
483 break;
484
485 case WebThemeEngine::PartMenuList:
486 if (extraParams->menuList.fillContentArea) {
487 box(canvas, irect, extraParams->menuList.backgroundColor);
488 } else {
489 cc::PaintFlags flags;
490 flags.setColor(edgeColor);
491 flags.setStyle(cc::PaintFlags::kStroke_Style);
492 canvas->drawIRect(irect, flags);
493 }
494
495 // clip the drop-down arrow to be inside the select box
496 irect.fLeft =
497 std::max(irect.fLeft, extraParams->menuList.arrowX -
498 (extraParams->menuList.arrowSize + 1) / 2);
499 irect.fRight =
500 std::min(irect.fLeft + extraParams->menuList.arrowSize, irect.fRight);
501
502 irect.fTop = extraParams->menuList.arrowY -
503 (extraParams->menuList.arrowSize) / 2;
504 irect.fBottom = irect.fTop + (extraParams->menuList.arrowSize);
505
506 halfWidth = irect.width() / 2;
507 quarterWidth = irect.width() / 4;
508
509 if (state == WebThemeEngine::StateFocused) // FIXME: draw differenty?
510 state = WebThemeEngine::StateNormal;
511 box(canvas, irect, bgColors(state));
512 triangle(canvas, irect.fLeft + quarterWidth, irect.fTop + quarterWidth,
513 irect.fRight - quarterWidth, irect.fTop + quarterWidth,
514 irect.fLeft + halfWidth, irect.fBottom - quarterWidth,
515 edgeColor);
516
517 break;
518
519 case WebThemeEngine::PartSliderTrack: {
520 SkIRect lirect = irect;
521
522 // Draw a narrow rect for the track plus box hatches on the ends.
523 if (state == WebThemeEngine::StateFocused) // FIXME: draw differently?
524 state = WebThemeEngine::StateNormal;
525 if (extraParams->slider.vertical) {
526 lirect.inset(halfWidth - sliderIndent, noOffset);
527 box(canvas, lirect, bgColors(state));
528 line(canvas, left, top, right, top, edgeColor);
529 line(canvas, left, bottom, right, bottom, edgeColor);
530 } else {
531 lirect.inset(noOffset, halfHeight - sliderIndent);
532 box(canvas, lirect, bgColors(state));
533 line(canvas, left, top, left, bottom, edgeColor);
534 line(canvas, right, top, right, bottom, edgeColor);
535 }
536 break;
537 }
538
539 case WebThemeEngine::PartSliderThumb:
540 if (state == WebThemeEngine::StateFocused) // FIXME: draw differently?
541 state = WebThemeEngine::StateNormal;
542 oval(canvas, irect, bgColors(state));
543 break;
544
545 case WebThemeEngine::PartInnerSpinButton: {
546 // stack half-height up and down arrows on top of each other
547 SkIRect lirect;
548 int halfHeight = rect.height / 2;
549 if (extraParams->innerSpin.readOnly)
550 state = blink::WebThemeEngine::StateDisabled;
551
552 lirect.set(rect.x, rect.y, rect.x + rect.width - 1,
553 rect.y + halfHeight - 1);
554 box(canvas, lirect, bgColors(state));
555 bottom = lirect.fBottom;
556 quarterHeight = lirect.height() / 4;
557 triangle(canvas, left + quarterWidth, bottom - quarterHeight,
558 right - quarterWidth, bottom - quarterHeight, left + halfWidth,
559 top + quarterHeight, edgeColor);
560
561 lirect.set(rect.x, rect.y + halfHeight, rect.x + rect.width - 1,
562 rect.y + 2 * halfHeight - 1);
563 top = lirect.fTop;
564 bottom = lirect.fBottom;
565 quarterHeight = lirect.height() / 4;
566 box(canvas, lirect, bgColors(state));
567 triangle(canvas, left + quarterWidth, top + quarterHeight,
568 right - quarterWidth, top + quarterHeight, left + halfWidth,
569 bottom - quarterHeight, edgeColor);
570 markState(canvas, irect, state);
571 break;
572 }
573 case WebThemeEngine::PartProgressBar: {
574 flags.setColor(bgColors(state));
575 flags.setStyle(cc::PaintFlags::kFill_Style);
576 canvas->drawIRect(irect, flags);
577
578 // Emulate clipping
579 SkIRect tofill = irect;
580 if (extraParams->progressBar.determinate) {
581 tofill.set(extraParams->progressBar.valueRectX,
582 extraParams->progressBar.valueRectY,
583 extraParams->progressBar.valueRectX +
584 extraParams->progressBar.valueRectWidth - 1,
585 extraParams->progressBar.valueRectY +
586 extraParams->progressBar.valueRectHeight);
587 }
588
589 if (!tofill.intersect(irect))
590 tofill.setEmpty();
591
592 flags.setColor(edgeColor);
593 flags.setStyle(cc::PaintFlags::kFill_Style);
594 canvas->drawIRect(tofill, flags);
595
596 markState(canvas, irect, state);
597 break;
598 }
599 default:
600 // FIXME: Should we do something here to indicate that we got an invalid
601 // part?
602 // Unfortunately, we can't assert because we don't have access to WTF or
603 // base.
604 break;
605 }
606 }
607
608 } // namespace test_runner
609
610 #endif // !defined(OS_MACOSX)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698