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