#include "webkit/tools/test_shell/test_shell_webthemecontrol.h"
#include "base/logging.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
namespace TestShellWebTheme {
const SkColor kEdgeColor = SK_ColorBLACK;
const SkColor kReadOnlyColor = SkColorSetRGB(0xe9, 0xc2, 0xa6);
const SkColor kFgColor = SK_ColorBLACK;
const SkColor kBgColors[] = {
SK_ColorBLACK,
SkColorSetRGB(0xc9, 0xc9, 0xc9),
SkColorSetRGB(0xf3, 0xe0, 0xd0),
SkColorSetRGB(0x89, 0xc4, 0xff),
SkColorSetRGB(0x43, 0xf9, 0xff),
SkColorSetRGB(0x20, 0xf6, 0xcc),
SkColorSetRGB(0x00, 0xf3, 0xac),
SkColorSetRGB(0xa9, 0xff, 0x12),
SkColorSetRGB(0xcc, 0xcc, 0xcc)
};
SkIRect Validate(const SkIRect& rect, Control::Type ctype) {
SkIRect retval = rect;
if (ctype == Control::kUncheckedBox_Type ||
ctype == Control::kCheckedBox_Type ||
ctype == Control::kUncheckedRadio_Type ||
ctype == Control::kCheckedRadio_Type) {
const int kMaxControlSize = 13;
int control_size = std::min(rect.width(), rect.height());
control_size = std::min(control_size, kMaxControlSize);
retval.fLeft = rect.fLeft + (rect.width() / 2) - (control_size / 2);
retval.fRight = retval.fLeft + control_size - 1;
retval.fTop = rect.fTop + (rect.height() / 2) - (control_size / 2);
retval.fBottom = retval.fTop + control_size - 1;
}
return retval;
}
Control::Control(SkCanvas* canvas, const SkIRect& irect,
Type ctype, State cstate)
: canvas_(canvas),
irect_(Validate(irect, ctype)),
type_(ctype),
state_(cstate),
left_(irect_.fLeft),
right_(irect_.fRight),
top_(irect_.fTop),
bottom_(irect_.fBottom),
height_(irect_.height()),
width_(irect_.width()),
edge_color_(kEdgeColor),
bg_color_(kBgColors[cstate]),
fg_color_(kFgColor) {
}
Control::~Control() {
}
void Control::box(const SkIRect& rect, SkColor fill_color) {
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(fill_color);
canvas_->drawIRect(rect, paint);
paint.setColor(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawIRect(rect, paint);
}
void Control::line(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 Control::triangle(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(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawPath(path, paint);
}
void Control::roundRect(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(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawRoundRect(rect, radius, radius, paint);
}
void Control::oval(SkColor color) {
SkRect rect;
SkPaint paint;
rect.set(irect_);
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
canvas_->drawOval(rect, paint);
paint.setColor(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawOval(rect, paint);
}
void Control::circle(SkScalar radius, SkColor color) {
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(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawCircle(cx, cy, radius, paint);
}
void Control::nested_boxes(int indent_left, int indent_top,
int indent_right, int indent_bottom,
SkColor outer_color, SkColor inner_color) {
SkIRect lirect;
box(irect_, outer_color);
lirect.set(irect_.fLeft + indent_left, irect_.fTop + indent_top,
irect_.fRight - indent_right, irect_.fBottom - indent_bottom);
box(lirect, inner_color);
}
void Control::markState() {
const int kReadOnlyLineOffset = 5;
const int kTriangleSize = 5;
switch (state_) {
case kUnknown_State:
case kDisabled_State:
case kNormal_State:
break;
case kReadOnly_State:
for (int i = top_ + kReadOnlyLineOffset; i < bottom_ ;
i += kReadOnlyLineOffset) {
line(left_ + 1, i, right_ - 1, i, kReadOnlyColor);
}
break;
case kHot_State:
triangle(left_, top_,
left_ + kTriangleSize, top_,
left_, top_ + kTriangleSize, edge_color_);
break;
case kHover_State:
triangle(right_, top_,
right_, top_ + kTriangleSize,
right_ - kTriangleSize, top_, edge_color_);
break;
case kFocused_State:
triangle(right_, bottom_,
right_ - kTriangleSize, bottom_,
right_, bottom_ - kTriangleSize, edge_color_);
break;
case kPressed_State:
triangle(left_, bottom_,
left_, bottom_ - kTriangleSize,
left_ + kTriangleSize, bottom_, edge_color_);
break;
default:
NOTREACHED();
break;
}
}
void Control::draw() {
int half_width = width_ / 2;
int half_height = height_ / 2;
int quarter_width = width_ / 4;
int quarter_height = height_ / 4;
const int kCheckIndent = 3;
const int kNotchLongOffset = 1;
const int kNotchShortOffset = 4;
const int kNoOffset = 0;
int short_offset;
int long_offset;
const int kThumbLongIndent = 0;
const int kThumbShortIndent = 2;
const int kGripLongIndent = 3;
const int kGripShortIndent = 5;
const int kSliderIndent = 2;
skia::ScopedPlatformPaint scoped_platform_paint(canvas_);
switch (type_) {
case kUnknown_Type:
NOTREACHED();
break;
case kTextField_Type:
NOTREACHED();
break;
case kPushButton_Type:
roundRect(bg_color_);
break;
case kUncheckedBox_Type:
box(irect_, bg_color_);
break;
case kCheckedBox_Type:
nested_boxes(kCheckIndent, kCheckIndent, kCheckIndent, kCheckIndent,
bg_color_, fg_color_);
break;
case kIndeterminateCheckBox_Type:
nested_boxes(kCheckIndent, height_ / 2, kCheckIndent, height_ / 2,
bg_color_, fg_color_);
break;
case kUncheckedRadio_Type:
circle(SkIntToScalar(half_height), bg_color_);
break;
case kCheckedRadio_Type:
circle(SkIntToScalar(half_height), bg_color_);
circle(SkIntToScalar(half_height - kCheckIndent), fg_color_);
break;
case kHorizontalScrollTrackBack_Type:
long_offset = half_height - kNotchLongOffset;
short_offset = width_ - kNotchShortOffset;
nested_boxes(kNoOffset, long_offset, short_offset, long_offset,
bg_color_, edge_color_);
break;
case kHorizontalScrollTrackForward_Type:
long_offset = half_height - kNotchLongOffset;
short_offset = width_ - kNotchShortOffset;
nested_boxes(short_offset, long_offset, kNoOffset, long_offset,
bg_color_, fg_color_);
break;
case kVerticalScrollTrackBack_Type:
long_offset = half_width - kNotchLongOffset;
short_offset = height_ - kNotchShortOffset;
nested_boxes(long_offset, kNoOffset, long_offset, short_offset,
bg_color_, fg_color_);
break;
case kVerticalScrollTrackForward_Type:
long_offset = half_width - kNotchLongOffset;
short_offset = height_ - kNotchShortOffset;
nested_boxes(long_offset, short_offset, long_offset, kNoOffset,
bg_color_, fg_color_);
break;
case kHorizontalScrollThumb_Type:
nested_boxes(kThumbLongIndent, kThumbShortIndent, kThumbLongIndent,
kThumbShortIndent, bg_color_, bg_color_);
break;
case kVerticalScrollThumb_Type:
nested_boxes(kThumbShortIndent, kThumbLongIndent, kThumbShortIndent,
kThumbLongIndent, bg_color_, bg_color_);
break;
case kHorizontalSliderThumb_Type:
oval(bg_color_);
break;
case kHorizontalScrollGrip_Type:
long_offset = half_width - kGripLongIndent;
line(left_ + kGripLongIndent, top_ + half_height,
right_ - kGripLongIndent, top_ + half_height, fg_color_);
line(left_ + long_offset, top_ + kGripShortIndent,
left_ + long_offset, bottom_ - kGripShortIndent, fg_color_);
line(right_ - long_offset, top_ + kGripShortIndent,
right_ - long_offset, bottom_ - kGripShortIndent, fg_color_);
break;
case kVerticalScrollGrip_Type:
long_offset = half_height - kGripLongIndent;
line(left_ + half_width, top_ + kGripLongIndent,
left_ + half_width, bottom_ - kGripLongIndent, fg_color_);
line(left_ + kGripShortIndent, top_ + long_offset,
right_ - kGripShortIndent, top_ + long_offset, fg_color_);
line(left_ + kGripShortIndent, bottom_ - long_offset,
right_ - kGripShortIndent, bottom_ - long_offset, fg_color_);
break;
case kLeftArrow_Type:
box(irect_, bg_color_);
triangle(right_ - quarter_width, top_ + quarter_height,
right_ - quarter_width, bottom_ - quarter_height,
left_ + quarter_width, top_ + half_height, fg_color_);
break;
case kRightArrow_Type:
box(irect_, bg_color_);
triangle(left_ + quarter_width, top_ + quarter_height,
right_ - quarter_width, top_ + half_height,
left_ + quarter_width, bottom_ - quarter_height, fg_color_);
break;
case kUpArrow_Type:
box(irect_, bg_color_);
triangle(left_ + quarter_width, bottom_ - quarter_height,
left_ + half_width, top_ + quarter_height,
right_ - quarter_width, bottom_ - quarter_height, fg_color_);
break;
case kDownArrow_Type:
box(irect_, bg_color_);
triangle(left_ + quarter_width, top_ + quarter_height,
right_ - quarter_width, top_ + quarter_height,
left_ + half_width, bottom_ - quarter_height, fg_color_);
break;
case kHorizontalSliderTrack_Type:
SkIRect lirect;
lirect = irect_;
lirect.inset(kNoOffset, half_height - kSliderIndent);
box(lirect, bg_color_);
line(left_, top_, left_, bottom_, edge_color_);
line(right_, top_, right_, bottom_, edge_color_);
break;
case kDropDownButton_Type:
box(irect_, bg_color_);
triangle(left_ + quarter_width, top_,
right_ - quarter_width, top_,
left_ + half_width, bottom_, fg_color_);
break;
default:
NOTREACHED();
break;
}
markState();
}
void Control::drawTextField(bool draw_edges, bool fill_content_area,
SkColor color) {
SkPaint paint;
skia::ScopedPlatformPaint scoped_platform_paint(canvas_);
if (fill_content_area) {
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
canvas_->drawIRect(irect_, paint);
}
if (draw_edges) {
paint.setColor(edge_color_);
paint.setStyle(SkPaint::kStroke_Style);
canvas_->drawIRect(irect_, paint);
}
markState();
}
void
Control::drawProgressBar(const SkIRect& fill_rect) {
SkPaint paint;
skia::ScopedPlatformPaint scoped_platform_paint(canvas_);
paint.setColor(bg_color_);
paint.setStyle(SkPaint::kFill_Style);
canvas_->drawIRect(irect_, paint);
SkIRect tofill;
tofill.intersect(irect_, fill_rect);
paint.setColor(fg_color_);
paint.setStyle(SkPaint::kFill_Style);
canvas_->drawIRect(tofill, paint);
markState();
}
}