void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect)
{
    const bool hovered = scrollbar->hoveredPart() == ThumbPart;
    const int midx = rect.x() + rect.width() / 2;
    const int midy = rect.y() + rect.height() / 2;
    const bool vertical = scrollbar->orientation() == VerticalScrollbar;
    SkCanvas* const canvas = gc->platformContext()->canvas();

    SkScalar thumb[3];
    SkColorToHSV(hovered
                 ? PlatformThemeChromiumGtk::thumbActiveColor()
                 : PlatformThemeChromiumGtk::thumbInactiveColor(),
                 thumb);

    SkPaint paint;
    paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(thumb, 0, 0.02));

    SkIRect skrect;
    if (vertical)
        skrect.set(rect.x(), rect.y(), midx + 1, rect.y() + rect.height());
    else
        skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), midy + 1);

    canvas->drawIRect(skrect, paint);

    paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(thumb, 0, -0.02));

    if (vertical)
        skrect.set(midx + 1, rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
    else
        skrect.set(rect.x(), midy + 1, rect.x() + rect.width(), rect.y() + rect.height());

    canvas->drawIRect(skrect, paint);

    SkScalar track[3];
    SkColorToHSV(PlatformThemeChromiumGtk::trackColor(), track);
    paint.setColor(PlatformThemeChromiumGtk::outlineColor(track, thumb));
    drawBox(canvas, rect, paint);

    if (rect.height() > 10 && rect.width() > 10) {
        const int grippyHalfWidth = 2;
        const int interGrippyOffset = 3;
        if (vertical) {
            drawHorizLine(canvas, midx - grippyHalfWidth, midx + grippyHalfWidth, midy - interGrippyOffset, paint);
            drawHorizLine(canvas, midx - grippyHalfWidth, midx + grippyHalfWidth, midy,                     paint);
            drawHorizLine(canvas, midx - grippyHalfWidth, midx + grippyHalfWidth, midy + interGrippyOffset, paint);
        } else {
            drawVertLine(canvas, midx - interGrippyOffset, midy - grippyHalfWidth, midy + grippyHalfWidth, paint);
            drawVertLine(canvas, midx,                     midy - grippyHalfWidth, midy + grippyHalfWidth, paint);
            drawVertLine(canvas, midx + interGrippyOffset, midy - grippyHalfWidth, midy + grippyHalfWidth, paint);
        }
    }
}
void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart partType)
{
    SkCanvas* const canvas = gc->platformContext()->canvas();
    SkPaint paint;
    SkIRect skrect;

    skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
    SkScalar trackHSV[3];
    SkColorToHSV(PlatformThemeChromiumGtk::trackColor(), trackHSV);
    paint.setColor(PlatformThemeChromiumGtk::saturateAndBrighten(trackHSV, 0, 0));
    canvas->drawIRect(skrect, paint);

    SkScalar thumbHSV[3];
    SkColorToHSV(PlatformThemeChromiumGtk::thumbInactiveColor(),
                 thumbHSV);

    paint.setColor(PlatformThemeChromiumGtk::outlineColor(trackHSV, thumbHSV));
    drawBox(canvas, rect, paint);
}
void PlatformThemeChromiumLinux::paintArrowButton(GraphicsContext* gc, const IntRect& rect, ArrowDirection direction, ControlStates states)
{
    SkCanvas* const canvas = gc->platformContext()->canvas();
    int widthMiddle, lengthMiddle;
    SkPaint paint;
    if (direction == North || direction == South) {
        widthMiddle = rect.width() / 2 + 1;
        lengthMiddle = rect.height() / 2 + 1;
    } else {
        lengthMiddle = rect.width() / 2 + 1;
        widthMiddle = rect.height() / 2 + 1;
    }

    // Calculate button color.
    SkScalar trackHSV[3];
    SkColorToHSV(trackColor(), trackHSV);
    SkColor buttonColor = saturateAndBrighten(trackHSV, 0, 0.2);
    SkColor backgroundColor = buttonColor;
    if (states & PressedState) {
        SkScalar buttonHSV[3];
        SkColorToHSV(buttonColor, buttonHSV);
        buttonColor = saturateAndBrighten(buttonHSV, 0, -0.1);
    } else if (states & HoverState) {
        SkScalar buttonHSV[3];
        SkColorToHSV(buttonColor, buttonHSV);
        buttonColor = saturateAndBrighten(buttonHSV, 0, 0.05);
    }

    SkIRect skrect;
    skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
    // Paint the background (the area visible behind the rounded corners).
    paint.setColor(backgroundColor);
    canvas->drawIRect(skrect, paint);

    // Paint the button's outline and fill the middle
    SkPath outline;
    switch (direction) {
    case North:
        outline.moveTo(rect.x() + 0.5, rect.y() + rect.height() + 0.5);
        outline.rLineTo(0, -(rect.height() - 2));
        outline.rLineTo(2, -2);
        outline.rLineTo(rect.width() - 5, 0);
        outline.rLineTo(2, 2);
        outline.rLineTo(0, rect.height() - 2);
        break;
    case South:
        outline.moveTo(rect.x() + 0.5, rect.y() - 0.5);
        outline.rLineTo(0, rect.height() - 2);
        outline.rLineTo(2, 2);
        outline.rLineTo(rect.width() - 5, 0);
        outline.rLineTo(2, -2);
        outline.rLineTo(0, -(rect.height() - 2));
        break;
    case East:
        outline.moveTo(rect.x() - 0.5, rect.y() + 0.5);
        outline.rLineTo(rect.width() - 2, 0);
        outline.rLineTo(2, 2);
        outline.rLineTo(0, rect.height() - 5);
        outline.rLineTo(-2, 2);
        outline.rLineTo(-(rect.width() - 2), 0);
        break;
    case West:
        outline.moveTo(rect.x() + rect.width() + 0.5, rect.y() + 0.5);
        outline.rLineTo(-(rect.width() - 2), 0);
        outline.rLineTo(-2, 2);
        outline.rLineTo(0, rect.height() - 5);
        outline.rLineTo(2, 2);
        outline.rLineTo(rect.width() - 2, 0);
        break;
    }
    outline.close();

    paint.setStyle(SkPaint::kFill_Style);
    paint.setColor(buttonColor);
    canvas->drawPath(outline, paint);

    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    SkScalar thumbHSV[3];
    SkColorToHSV(thumbInactiveColor(), thumbHSV);
    paint.setColor(outlineColor(trackHSV, thumbHSV));
    canvas->drawPath(outline, paint);

    // If the button is disabled or read-only, the arrow is drawn with the outline color.
    if (states & EnabledState && !(states & ReadOnlyState))
        paint.setColor(SK_ColorBLACK);

    paint.setAntiAlias(false);
    paint.setStyle(SkPaint::kFill_Style);

    SkPath path;
    // The constants in this block of code are hand-tailored to produce good
    // looking arrows without anti-aliasing.
    switch (direction) {
    case North:
        path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle + 2);
        path.rLineTo(7, 0);
        path.rLineTo(-4, -4);
        break;
    case South:
        path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle - 3);
        path.rLineTo(7, 0);
        path.rLineTo(-4, 4);
        break;
    case East:
        path.moveTo(rect.x() + lengthMiddle - 3, rect.y() + widthMiddle - 4);
        path.rLineTo(0, 7);
        path.rLineTo(4, -4);
        break;
    case West:
        path.moveTo(rect.x() + lengthMiddle + 1, rect.y() + widthMiddle - 5);
        path.rLineTo(0, 9);
        path.rLineTo(-4, -4);
        break;
    }
    path.close();

    canvas->drawPath(path, paint);
}