This source file includes following definitions.
- bgColors
- getSize
- webRectToSkIRect
- validate
- box
- line
- triangle
- roundRect
- oval
- circle
- nestedBoxes
- markState
- paint
#include "content/shell/renderer/test_runner/WebTestThemeEngineMock.h"
#include "base/logging.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/skia/include/core/SkRect.h"
using blink::WebCanvas;
using blink::WebColor;
using blink::WebRect;
using blink::WebThemeEngine;
namespace WebTestRunner {
static const SkColor edgeColor = SK_ColorBLACK;
static const SkColor readOnlyColor = SkColorSetRGB(0xe9, 0xc2, 0xa6);
SkColor bgColors(WebThemeEngine::State state) {
switch (state) {
case WebThemeEngine::StateDisabled:
return SkColorSetRGB(0xc9, 0xc9, 0xc9);
case WebThemeEngine::StateHover:
return SkColorSetRGB(0x43, 0xf9, 0xff);
case WebThemeEngine::StateNormal:
return SkColorSetRGB(0x89, 0xc4, 0xff);
case WebThemeEngine::StatePressed:
return SkColorSetRGB(0xa9, 0xff, 0x12);
case WebThemeEngine::StateFocused:
return SkColorSetRGB(0x00, 0xf3, 0xac);
case WebThemeEngine::StateReadonly:
return SkColorSetRGB(0xf3, 0xe0, 0xd0);
default:
NOTREACHED();
}
return SkColorSetRGB(0x00, 0x00, 0xff);
}
blink::WebSize WebTestThemeEngineMock::getSize(WebThemeEngine::Part part)
{
const blink::WebSize invalidPartSize = blink::WebSize(100, 100);
switch (part) {
case WebThemeEngine::PartScrollbarLeftArrow:
return blink::WebSize(17, 15);
case WebThemeEngine::PartScrollbarRightArrow:
return invalidPartSize;
case WebThemeEngine::PartScrollbarUpArrow:
return blink::WebSize(15, 17);
case WebThemeEngine::PartScrollbarDownArrow:
return invalidPartSize;
case WebThemeEngine::PartScrollbarHorizontalThumb:
return blink::WebSize(15, 15);
case WebThemeEngine::PartScrollbarVerticalThumb:
return blink::WebSize(15, 15);
case WebThemeEngine::PartScrollbarHorizontalTrack:
return blink::WebSize(0, 15);
case WebThemeEngine::PartScrollbarVerticalTrack:
return blink::WebSize(15, 0);
case WebThemeEngine::PartCheckbox:
case WebThemeEngine::PartRadio:
return blink::WebSize(13, 13);
case WebThemeEngine::PartSliderThumb:
return blink::WebSize(11, 21);
case WebThemeEngine::PartInnerSpinButton:
return blink::WebSize(15, 8);
default:
return invalidPartSize;
}
}
static SkIRect webRectToSkIRect(const WebRect& webRect)
{
SkIRect irect;
irect.set(webRect.x, webRect.y,
webRect.x + webRect.width - 1, webRect.y + webRect.height - 1);
return irect;
}
static SkIRect validate(const SkIRect& rect, WebThemeEngine::Part part)
{
switch (part) {
case WebThemeEngine::PartCheckbox:
case WebThemeEngine::PartRadio: {
SkIRect retval = rect;
const int maxControlSize = 13;
int controlSize = std::min(rect.width(), rect.height());
controlSize = std::min(controlSize, maxControlSize);
retval.fLeft = rect.fLeft + (rect.width() / 2) - (controlSize / 2);
retval.fRight = retval.fLeft + controlSize - 1;
retval.fTop = rect.fTop + (rect.height() / 2) - (controlSize / 2);
retval.fBottom = retval.fTop + controlSize - 1;
return retval;
}
default:
return rect;
}
}
void box(SkCanvas *canvas, const SkIRect& rect, SkColor fillColor)
{
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(fillColor);
canvas->drawIRect(rect, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawIRect(rect, paint);
}
void line(SkCanvas *canvas, int x0, int y0, int x1, int y1, SkColor color)
{
SkPaint paint;
paint.setColor(color);
canvas->drawLine(SkIntToScalar(x0), SkIntToScalar(y0),
SkIntToScalar(x1), SkIntToScalar(y1), paint);
}
void triangle(SkCanvas *canvas,
int x0, int y0,
int x1, int y1,
int x2, int y2,
SkColor color)
{
SkPath path;
SkPaint paint;
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
path.incReserve(4);
path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0));
path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1));
path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2));
path.close();
canvas->drawPath(path, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawPath(path, paint);
}
void roundRect(SkCanvas *canvas, SkIRect irect, SkColor color)
{
SkRect rect;
SkScalar radius = SkIntToScalar(5);
SkPaint paint;
rect.set(irect);
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
canvas->drawRoundRect(rect, radius, radius, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRoundRect(rect, radius, radius, paint);
}
void oval(SkCanvas* canvas, SkIRect irect, SkColor color)
{
SkRect rect;
SkPaint paint;
rect.set(irect);
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
canvas->drawOval(rect, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawOval(rect, paint);
}
void circle(SkCanvas *canvas, SkIRect irect, SkScalar radius, SkColor color)
{
int left = irect.fLeft;
int width = irect.width();
int height = irect.height();
int top = irect.fTop;
SkScalar cy = SkIntToScalar(top + height / 2);
SkScalar cx = SkIntToScalar(left + width / 2);
SkPaint paint;
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
canvas->drawCircle(cx, cy, radius, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawCircle(cx, cy, radius, paint);
}
void nestedBoxes(SkCanvas *canvas,
SkIRect irect,
int indentLeft,
int indentTop,
int indentRight,
int indentBottom,
SkColor outerColor,
SkColor innerColor)
{
SkIRect lirect;
box(canvas, irect, outerColor);
lirect.set(irect.fLeft + indentLeft,
irect.fTop + indentTop,
irect.fRight - indentRight,
irect.fBottom - indentBottom);
box(canvas, lirect, innerColor);
}
void markState(SkCanvas *canvas, SkIRect irect, WebThemeEngine::State state)
{
int left = irect.fLeft;
int right = irect.fRight;
int top = irect.fTop;
int bottom = irect.fBottom;
const int triangleSize = 5;
switch (state) {
case WebThemeEngine::StateDisabled:
case WebThemeEngine::StateNormal:
break;
case WebThemeEngine::StateReadonly: {
const int readOnlyLineOffset = 5;
for (int i = top + readOnlyLineOffset; i < bottom; i += readOnlyLineOffset)
line(canvas, left + 1, i, right - 1, i, readOnlyColor);
break;
}
case WebThemeEngine::StateHover:
triangle(canvas,
left, top,
left + triangleSize, top,
left, top + triangleSize,
edgeColor);
break;
case WebThemeEngine::StateFocused:
triangle(canvas,
right, bottom,
right - triangleSize, bottom,
right, bottom - triangleSize,
edgeColor);
break;
case WebThemeEngine::StatePressed:
triangle(canvas,
left, bottom,
left, bottom - triangleSize,
left + triangleSize, bottom,
edgeColor);
break;
default:
break;
}
}
void WebTestThemeEngineMock::paint(
blink::WebCanvas* canvas,
WebThemeEngine::Part part,
WebThemeEngine::State state,
const blink::WebRect& rect,
const WebThemeEngine::ExtraParams* extraParams)
{
SkIRect irect = webRectToSkIRect(rect);
SkPaint paint;
const int checkIndent = 3;
const int notchLongOffset = 1;
const int notchShortOffset = 4;
const int noOffset = 0;
const int thumbLongIndent = 0;
const int thumbShortIndent = 2;
const int gripLongIndent = 3;
const int gripShortIndent = 5;
const int sliderIndent = 2;
int halfHeight = irect.height() / 2;
int halfWidth = irect.width() / 2;
int quarterHeight = irect.height() / 4;
int quarterWidth = irect.width() / 4;
int left = irect.fLeft;
int right = irect.fRight;
int top = irect.fTop;
int bottom = irect.fBottom;
switch (part) {
case WebThemeEngine::PartScrollbarDownArrow:
box(canvas, irect, bgColors(state));
triangle(canvas,
left + quarterWidth, top + quarterHeight,
right - quarterWidth, top + quarterHeight,
left + halfWidth, bottom - quarterHeight,
edgeColor);
markState(canvas, irect, state);
break;
case WebThemeEngine::PartScrollbarLeftArrow:
box(canvas, irect, bgColors(state));
triangle(canvas,
right - quarterWidth, top + quarterHeight,
right - quarterWidth, bottom - quarterHeight,
left + quarterWidth, top + halfHeight,
edgeColor);
break;
case WebThemeEngine::PartScrollbarRightArrow:
box(canvas, irect, bgColors(state));
triangle(canvas,
left + quarterWidth, top + quarterHeight,
right - quarterWidth, top + halfHeight,
left + quarterWidth, bottom - quarterHeight,
edgeColor);
break;
case WebThemeEngine::PartScrollbarUpArrow:
box(canvas, irect, bgColors(state));
triangle(canvas,
left + quarterWidth, bottom - quarterHeight,
left + halfWidth, top + quarterHeight,
right - quarterWidth, bottom - quarterHeight,
edgeColor);
markState(canvas, irect, state);
break;
case WebThemeEngine::PartScrollbarHorizontalThumb: {
nestedBoxes(canvas, irect, thumbLongIndent, thumbShortIndent,
thumbLongIndent, thumbShortIndent,
bgColors(state), bgColors(state));
int longOffset = halfWidth - gripLongIndent;
line(canvas,
left + gripLongIndent, top + halfHeight,
right - gripLongIndent, top + halfHeight,
edgeColor);
line(canvas,
left + longOffset, top + gripShortIndent,
left + longOffset, bottom - gripShortIndent,
edgeColor);
line(canvas,
right - longOffset, top + gripShortIndent,
right - longOffset, bottom - gripShortIndent,
edgeColor);
markState(canvas, irect, state);
break;
}
case WebThemeEngine::PartScrollbarVerticalThumb: {
nestedBoxes(canvas, irect, thumbShortIndent, thumbLongIndent,
thumbShortIndent, thumbLongIndent,
bgColors(state), bgColors(state));
int longOffset = halfHeight - gripLongIndent;
line(canvas,
left + halfWidth, top + gripLongIndent,
left + halfWidth, bottom - gripLongIndent,
edgeColor);
line(canvas,
left + gripShortIndent, top + longOffset,
right - gripShortIndent, top + longOffset,
edgeColor);
line(canvas,
left + gripShortIndent, bottom - longOffset,
right - gripShortIndent, bottom - longOffset,
edgeColor);
markState(canvas, irect, state);
break;
}
case WebThemeEngine::PartScrollbarHorizontalTrack: {
int longOffset = halfHeight - notchLongOffset;
int shortOffset = irect.width() - notchShortOffset;
if (extraParams->scrollbarTrack.isBack) {
nestedBoxes(canvas, irect, noOffset, longOffset, shortOffset,
longOffset, bgColors(state), edgeColor);
} else {
nestedBoxes(canvas, irect, shortOffset, longOffset, noOffset,
longOffset, bgColors(state), edgeColor);
}
markState(canvas, irect, state);
break;
}
case WebThemeEngine::PartScrollbarVerticalTrack: {
int longOffset = halfWidth - notchLongOffset;
int shortOffset = irect.height() - notchShortOffset;
if (extraParams->scrollbarTrack.isBack) {
nestedBoxes(canvas, irect, longOffset, noOffset, longOffset,
shortOffset, bgColors(state), edgeColor);
} else {
nestedBoxes(canvas, irect, longOffset, shortOffset, longOffset,
noOffset, bgColors(state), edgeColor);
}
markState(canvas, irect, state);
break;
}
case WebThemeEngine::PartScrollbarCorner: {
SkIRect cornerRect = {rect.x, rect.y, rect.x + rect.width, rect.y + rect.height};
paint.setColor(SK_ColorWHITE);
paint.setStyle(SkPaint::kFill_Style);
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setAntiAlias(true);
canvas->drawIRect(cornerRect, paint);
break;
}
case WebThemeEngine::PartCheckbox:
if (extraParams->button.indeterminate) {
nestedBoxes(canvas, irect,
checkIndent, halfHeight,
checkIndent, halfHeight,
bgColors(state), edgeColor);
} else if (extraParams->button.checked) {
irect = validate(irect, part);
nestedBoxes(canvas, irect,
checkIndent, checkIndent,
checkIndent, checkIndent,
bgColors(state), edgeColor);
} else {
irect = validate(irect, part);
box(canvas, irect, bgColors(state));
}
break;
case WebThemeEngine::PartRadio:
irect = validate(irect, part);
halfHeight = irect.height() / 2;
if (extraParams->button.checked) {
circle(canvas, irect, SkIntToScalar(halfHeight), bgColors(state));
circle(canvas, irect, SkIntToScalar(halfHeight - checkIndent), edgeColor);
} else {
circle(canvas, irect, SkIntToScalar(halfHeight), bgColors(state));
}
break;
case WebThemeEngine::PartButton:
roundRect(canvas, irect, bgColors(state));
markState(canvas, irect, state);
break;
case WebThemeEngine::PartTextField:
paint.setColor(extraParams->textField.backgroundColor);
paint.setStyle(SkPaint::kFill_Style);
canvas->drawIRect(irect, paint);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawIRect(irect, paint);
markState(canvas, irect, state);
break;
case WebThemeEngine::PartMenuList:
if (extraParams->menuList.fillContentArea) {
box(canvas, irect, extraParams->menuList.backgroundColor);
} else {
SkPaint paint;
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawIRect(irect, paint);
}
if (extraParams->menuList.arrowX - 4 > irect.fLeft)
irect.fLeft = extraParams->menuList.arrowX - 4;
if (extraParams->menuList.arrowX + 12 < irect.fRight)
irect.fRight = extraParams->menuList.arrowX + 12;
irect.fTop = extraParams->menuList.arrowY - (extraParams->menuList.arrowHeight) / 2;
irect.fBottom = extraParams->menuList.arrowY + (extraParams->menuList.arrowHeight - 1) / 2;
halfWidth = irect.width() / 2;
quarterWidth = irect.width() / 4;
if (state == WebThemeEngine::StateFocused)
state = WebThemeEngine::StateNormal;
box(canvas, irect, bgColors(state));
triangle(canvas,
irect.fLeft + quarterWidth, irect.fTop,
irect.fRight - quarterWidth, irect.fTop,
irect.fLeft + halfWidth, irect.fBottom,
edgeColor);
break;
case WebThemeEngine::PartSliderTrack: {
SkIRect lirect = irect;
if (state == WebThemeEngine::StateFocused)
state = WebThemeEngine::StateNormal;
if (extraParams->slider.vertical) {
lirect.inset(halfWidth - sliderIndent, noOffset);
box(canvas, lirect, bgColors(state));
line(canvas, left, top, right, top, edgeColor);
line(canvas, left, bottom, right, bottom, edgeColor);
} else {
lirect.inset(noOffset, halfHeight - sliderIndent);
box(canvas, lirect, bgColors(state));
line(canvas, left, top, left, bottom, edgeColor);
line(canvas, right, top, right, bottom, edgeColor);
}
break;
}
case WebThemeEngine::PartSliderThumb:
if (state == WebThemeEngine::StateFocused)
state = WebThemeEngine::StateNormal;
oval(canvas, irect, bgColors(state));
break;
case WebThemeEngine::PartInnerSpinButton: {
SkIRect lirect;
int halfHeight = rect.height / 2;
if (extraParams->innerSpin.readOnly)
state = blink::WebThemeEngine::StateDisabled;
lirect.set(rect.x, rect.y, rect.x + rect.width - 1, rect.y + halfHeight - 1);
box(canvas, lirect, bgColors(state));
bottom = lirect.fBottom;
quarterHeight = lirect.height() / 4;
triangle(canvas,
left + quarterWidth, bottom - quarterHeight,
right - quarterWidth, bottom - quarterHeight,
left + halfWidth, top + quarterHeight,
edgeColor);
lirect.set(rect.x, rect.y + halfHeight, rect.x + rect.width - 1,
rect.y + 2 * halfHeight - 1);
top = lirect.fTop;
bottom = lirect.fBottom;
quarterHeight = lirect.height() / 4;
box(canvas, lirect, bgColors(state));
triangle(canvas,
left + quarterWidth, top + quarterHeight,
right - quarterWidth, top + quarterHeight,
left + halfWidth, bottom - quarterHeight,
edgeColor);
markState(canvas, irect, state);
break;
}
case WebThemeEngine::PartProgressBar: {
paint.setColor(bgColors(state));
paint.setStyle(SkPaint::kFill_Style);
canvas->drawIRect(irect, paint);
SkIRect tofill = irect;
if (extraParams->progressBar.determinate) {
tofill.set(extraParams->progressBar.valueRectX,
extraParams->progressBar.valueRectY,
extraParams->progressBar.valueRectX +
extraParams->progressBar.valueRectWidth - 1,
extraParams->progressBar.valueRectY +
extraParams->progressBar.valueRectHeight);
}
tofill.intersect(irect, tofill);
paint.setColor(edgeColor);
paint.setStyle(SkPaint::kFill_Style);
canvas->drawIRect(tofill, paint);
markState(canvas, irect, state);
break;
}
default:
break;
}
}
}