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