Example #1
0
void paintSkiaText(GraphicsContext* context,
                   HFONT hfont,
                   int numGlyphs,
                   const WORD* glyphs,
                   const int* advances,
                   const GOFFSET* offsets,
                   const SkPoint* origin)
{
    HDC dc = GetDC(0);
    HGDIOBJ oldFont = SelectObject(dc, hfont);

    PlatformContextSkia* platformContext = context->platformContext();
    SkCanvas* canvas = platformContext->canvas();
    TextDrawingModeFlags textMode = platformContext->getTextDrawingMode();

    // If platformContext is GPU-backed make its GL context current.
    platformContext->makeGrContextCurrent();

    // Filling (if necessary). This is the common case.
    SkPaint paint;
    platformContext->setupPaintForFilling(&paint);
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    setupPaintForFont(hfont, &paint, platformContext);

    bool didFill = false;

    if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
        skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
        didFill = true;
    }

    // Stroking on top (if necessary).
    if ((textMode & TextModeStroke)
        && platformContext->getStrokeStyle() != NoStroke
        && platformContext->getStrokeThickness() > 0) {

        paint.reset();
        platformContext->setupPaintForStroking(&paint, 0, 0);
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        setupPaintForFont(hfont, &paint, platformContext);

        if (didFill) {
            // If there is a shadow and we filled above, there will already be
            // a shadow. We don't want to draw it again or it will be too dark
            // and it will go on top of the fill.
            //
            // Note that this isn't strictly correct, since the stroke could be
            // very thick and the shadow wouldn't account for this. The "right"
            // thing would be to draw to a new layer and then draw that layer
            // with a shadow. But this is a lot of extra work for something
            // that isn't normally an issue.
            paint.setLooper(0);
        }

        skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
    }

    SelectObject(dc, oldFont);
    ReleaseDC(0, dc);
}
void GraphicsContext::drawConvexPolygon(size_t numPoints,
                                        const FloatPoint* points,
                                        bool shouldAntialias)
{
    if (paintingDisabled())
        return;

    if (numPoints <= 1)
        return;

    SkPath path;
    setPathFromConvexPoints(&path, numPoints, points);

    SkPaint paint;
    platformContext()->setupPaintForFilling(&paint);
    paint.setAntiAlias(shouldAntialias);
    platformContext()->canvas()->drawPath(path, paint);
    platformContext()->didDrawPath(path, paint);

    if (strokeStyle() != NoStroke) {
        paint.reset();
        platformContext()->setupPaintForStroking(&paint, 0, 0);
        platformContext()->canvas()->drawPath(path, paint);
        platformContext()->didDrawPath(path, paint);
    }
}
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) {
    //此为canvas的save操作
	//在超过了作用域之后,会自动调用restore函数
    SkAutoCanvasRestore acr(canvas, true);

    SkPaint paint;
    SkScalar x = 0;
    const int scale = 64;

    //开启抗锯齿 : 见百度百科
    paint.setAntiAlias(true); 
    //绘制行首文字 : 见结果图每行行头文字
    const char* name = gConfigNames[bm.config()];
    canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8,
                     paint);

    //平移到(48, 0)???为何是48--牛群
    canvas->translate(SkIntToScalar(192), 0);
    //缩放 : x,y轴乘各乘以一个系数, 进行放大或缩小.: 此处因为4个像素很小,所以进行了放大.
    canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale));
    
    /*逐个画每行的6个方块*/
    //画前三个, 正常的, 滤镜的, 滤镜+防抖动的.
    x += draw_set(canvas, bm, 0, &paint);
    //画笔复原
    paint.reset();
    /*开启透明, 画后三个, 正常的, 滤镜的, 滤镜+防抖动的. */
    paint.setAlpha(0x80);
    draw_set(canvas, bm, x, &paint);
    return x * scale / 3;
}
void PlatformContextSkiaJava::drawRect(SkRect rect)
{
    SkPaint paint;
    int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000;
    if (fillcolorNotTransparent) {
        setupPaintForFilling(&paint);
        canvas()->drawRect(rect, paint);
    }

    if (m_state->m_strokeStyle != WebCore::NoStroke &&
        (m_state->m_strokeColor & 0xFF000000)) {
        // We do a fill of four rects to simulate the stroke of a border.
        SkColor oldFillColor = m_state->m_fillColor;

        // setFillColor() will set the shader to NULL, so save a ref to it now. 
        SkShader* oldFillShader = m_state->m_fillShader;
        oldFillShader->safeRef();
        setFillColor(m_state->m_strokeColor);
        paint.reset();
        setupPaintForFilling(&paint);
        SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
        canvas()->drawRect(topBorder, paint);
        SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom };
        canvas()->drawRect(bottomBorder, paint);
        SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 };
        canvas()->drawRect(leftBorder, paint);
        SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 };
        canvas()->drawRect(rightBorder, paint);
        setFillColor(oldFillColor);
        setFillShader(oldFillShader);
        oldFillShader->safeUnref();
    }
}
void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints,
                                                const FloatPoint* points,
                                                bool shouldAntialias)
{
    if (numPoints <= 1)
        return;

    SkPaint paint;
    SkPath path;

    path.incReserve(numPoints);
    path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
    for (size_t i = 1; i < numPoints; i++)
        path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));

    if (mCanvas->quickReject(path, shouldAntialias ?
            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
        return;
    }

    if (m_state->fillColor & 0xFF000000) {
        setupPaintFill(&paint);
        paint.setAntiAlias(shouldAntialias);
        mCanvas->drawPath(path, paint);
    }

    if (m_state->strokeStyle != NoStroke) {
        paint.reset();
        setupPaintStroke(&paint, 0);
        paint.setAntiAlias(shouldAntialias);
        mCanvas->drawPath(path, paint);
    }
}
Example #6
0
void PlatformContextSkia::drawRect(SkRect rect)
{
    SkPaint paint;
    int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000;
    if (fillcolorNotTransparent) {
        setupPaintForFilling(&paint);
        drawRect(rect, paint);
    }

    if (m_state->m_strokeStyle != NoStroke
        && (m_state->m_strokeColor & 0xFF000000)) {
        // We do a fill of four rects to simulate the stroke of a border.
        paint.reset();
        setupPaintForFilling(&paint);
        // need to jam in the strokeColor
        paint.setColor(this->effectiveStrokeColor());

        SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
        drawRect(topBorder, paint);
        SkRect bottomBorder = { rect.fLeft, rect.fBottom - 1, rect.fRight, rect.fBottom };
        drawRect(bottomBorder, paint);
        SkRect leftBorder = { rect.fLeft, rect.fTop + 1, rect.fLeft + 1, rect.fBottom - 1 };
        drawRect(leftBorder, paint);
        SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 };
        drawRect(rightBorder, paint);
    }
}
Example #7
0
void GraphicsContext::drawConvexPolygon(size_t numPoints,
                                        const FloatPoint* points,
                                        bool shouldAntialias)
{
    if (paintingDisabled())
        return;

    if (numPoints <= 1)
        return;

    platformContext()->prepareForSoftwareDraw();

    SkPath path;

    path.incReserve(numPoints);
    path.moveTo(WebCoreFloatToSkScalar(points[0].x()),
                WebCoreFloatToSkScalar(points[0].y()));
    for (size_t i = 1; i < numPoints; i++) {
        path.lineTo(WebCoreFloatToSkScalar(points[i].x()),
                    WebCoreFloatToSkScalar(points[i].y()));
    }

    if (!isPathSkiaSafe(getCTM(), path))
        return;

    SkPaint paint;
    platformContext()->setupPaintForFilling(&paint);
    platformContext()->canvas()->drawPath(path, paint);

    if (strokeStyle() != NoStroke) {
        paint.reset();
        platformContext()->setupPaintForStroking(&paint, 0, 0);
        platformContext()->canvas()->drawPath(path, paint);
    }
}
Example #8
0
void paintSkiaText(GraphicsContext* context,
                   HFONT hfont,
                   int numGlyphs,
                   const WORD* glyphs,
                   const int* advances,
                   const GOFFSET* offsets,
                   const SkPoint* origin)
{
    PlatformContextSkia* platformContext = context->platformContext();
    SkCanvas* canvas = platformContext->canvas();
    TextDrawingModeFlags textMode = platformContext->getTextDrawingMode();
    // Ensure font load for printing, because PDF device needs it.
    if (canvas->getTopDevice()->getDeviceCapabilities() & SkDevice::kVector_Capability)
        PlatformSupport::ensureFontLoaded(hfont);

    // Filling (if necessary). This is the common case.
    SkPaint paint;
    platformContext->setupPaintForFilling(&paint);
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    setupPaintForFont(hfont, &paint, platformContext);

    bool didFill = false;

    if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
        skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
        didFill = true;
    }

    // Stroking on top (if necessary).
    if ((textMode & TextModeStroke)
        && platformContext->getStrokeStyle() != NoStroke
        && platformContext->getStrokeThickness() > 0) {

        paint.reset();
        platformContext->setupPaintForStroking(&paint, 0, 0);
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        setupPaintForFont(hfont, &paint, platformContext);

        if (didFill) {
            // If there is a shadow and we filled above, there will already be
            // a shadow. We don't want to draw it again or it will be too dark
            // and it will go on top of the fill.
            //
            // Note that this isn't strictly correct, since the stroke could be
            // very thick and the shadow wouldn't account for this. The "right"
            // thing would be to draw to a new layer and then draw that layer
            // with a shadow. But this is a lot of extra work for something
            // that isn't normally an issue.
            paint.setLooper(0);
        }

        skiaDrawText(canvas, *origin, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
    }
}
static void paintSkiaText(GraphicsContext* context, HFONT hfont,
                          SkTypeface* face, float size, uint32_t textFlags,
                          int numGlyphs,
                          const WORD* glyphs,
                          const int* advances,
                          const GOFFSET* offsets,
                          const SkPoint& origin,
                          const SkRect& textRect)
{
    TextDrawingModeFlags textMode = context->textDrawingMode();
    // Ensure font load for printing, because PDF device needs it.
    if (context->isPrintingDevice())
        FontPlatformData::ensureFontLoaded(hfont);

    // Filling (if necessary). This is the common case.
    SkPaint paint;
    context->setupPaintForFilling(&paint);
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    setupPaintForFont(&paint, context, face, size, textFlags);

    bool didFill = false;

    if ((textMode & TextModeFill) && (SkColorGetA(paint.getColor()) || paint.getLooper())) {
        skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
        didFill = true;
    }

    // Stroking on top (if necessary).
    if ((textMode & TextModeStroke)
        && context->strokeStyle() != NoStroke
        && context->strokeThickness() > 0) {

        paint.reset();
        context->setupPaintForStroking(&paint);
        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        setupPaintForFont(&paint, context, face, size, textFlags);

        if (didFill) {
            // If there is a shadow and we filled above, there will already be
            // a shadow. We don't want to draw it again or it will be too dark
            // and it will go on top of the fill.
            //
            // Note that this isn't strictly correct, since the stroke could be
            // very thick and the shadow wouldn't account for this. The "right"
            // thing would be to draw to a new layer and then draw that layer
            // with a shadow. But this is a lot of extra work for something
            // that isn't normally an issue.
            paint.setLooper(0);
        }

        skiaDrawText(context, origin, textRect, &paint, &glyphs[0], &advances[0], &offsets[0], numGlyphs);
    }
}
Example #10
0
static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
                       SkGPipeState* state) {
    size_t offset = reader->offset();
    size_t stop = offset + PaintOp_unpackData(op32);
    SkPaint* p = state->editPaint();

    do {
        uint32_t p32 = reader->readU32();
        unsigned op = PaintOp_unpackOp(p32);
        unsigned data = PaintOp_unpackData(p32);

//        SkDebugf(" read %08X op=%d flags=%d data=%d\n", p32, op, done, data);

        switch (op) {
            case kReset_PaintOp: p->reset(); break;
            case kFlags_PaintOp: p->setFlags(data); break;
            case kColor_PaintOp: p->setColor(reader->readU32()); break;
            case kFilterLevel_PaintOp: p->setFilterQuality((SkFilterQuality)data); break;
            case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break;
            case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break;
            case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break;
            case kWidth_PaintOp: p->setStrokeWidth(reader->readScalar()); break;
            case kMiter_PaintOp: p->setStrokeMiter(reader->readScalar()); break;
            case kEncoding_PaintOp:
                p->setTextEncoding((SkPaint::TextEncoding)data);
                break;
            case kHinting_PaintOp: p->setHinting((SkPaint::Hinting)data); break;
            case kAlign_PaintOp: p->setTextAlign((SkPaint::Align)data); break;
            case kTextSize_PaintOp: p->setTextSize(reader->readScalar()); break;
            case kTextScaleX_PaintOp: p->setTextScaleX(reader->readScalar()); break;
            case kTextSkewX_PaintOp: p->setTextSkewX(reader->readScalar()); break;

            case kFlatIndex_PaintOp: {
                PaintFlats pf = (PaintFlats)PaintOp_unpackFlags(p32);
                unsigned index = data;
                set_paintflat(p, state->getFlat(index), pf);
                break;
            }

            case kTypeface_PaintOp:
                SkASSERT(SkToBool(state->getFlags() &
                                  SkGPipeWriter::kCrossProcess_Flag));
                p->setTypeface(state->getTypeface(data));
                break;
            default: SkDEBUGFAIL("bad paintop"); return;
        }
        SkASSERT(reader->offset() <= stop);
    } while (reader->offset() < stop);
}
void PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect)
{
    SkPaint paint;
    SkRect oval(rect);

    if (m_state->fillColor & 0xFF000000) {
        setupPaintFill(&paint);
        mCanvas->drawOval(oval, paint);
    }
    if (m_state->strokeStyle != NoStroke) {
        paint.reset();
        setupPaintStroke(&paint, &oval);
        mCanvas->drawOval(oval, paint);
    }
}
Example #12
0
void mbe_copy_source(mbe_t *src, mbe_t *dst) {
    SkPaint *paint = dst->paint;
    const SkBitmap *bmap;
    SkXfermode *mode;

    /* _prepare_paint(dst, SkPaint::kFill_Style); */
    mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
    paint->setXfermode(mode);
    bmap = &src->canvas->getDevice()->accessBitmap(false);

    dst->canvas->drawBitmap(*bmap, 0, 0, paint);

    paint->reset();
    mode->unref();
    /* _finish_paint(dst); */
}
// This method is only used to draw the little circles used in lists.
void GraphicsContext::drawEllipse(const IntRect& elipseRect)
{
    if (paintingDisabled())
        return;

    SkRect rect = elipseRect;
    SkPaint paint;
    platformContext()->setupPaintForFilling(&paint);
    platformContext()->canvas()->drawOval(rect, paint);
    platformContext()->didDrawBounded(rect, paint);

    if (strokeStyle() != NoStroke) {
        paint.reset();
        platformContext()->setupPaintForStroking(&paint, &rect, 0);
        platformContext()->canvas()->drawOval(rect, paint);
        platformContext()->didDrawBounded(rect, paint);
    }
}
// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
    if (paintingDisabled())
        return;

    SkPaint paint;
    SkRect  r(rect);

    if (fillColor().alpha()) {
        m_data->setup_paint_fill(&paint);
        GC2Canvas(this)->drawRect(r, paint);
    }
    
    if (strokeStyle() != NoStroke && strokeColor().alpha()) {
        paint.reset();
        m_data->setup_paint_stroke(&paint, &r);
        GC2Canvas(this)->drawRect(r, paint);
    }
}
void PlatformContextSkia::drawRect(SkRect rect)
{
    SkPaint paint;
    int fillcolorNotTransparent = m_state->m_fillColor & 0xFF000000;
    if (fillcolorNotTransparent) {
        setupPaintForFilling(&paint);
        canvas()->drawRect(rect, paint);
    }

    if (m_state->m_strokeStyle != WebCore::NoStroke &&
        (m_state->m_strokeColor & 0xFF000000)) {
        if (fillcolorNotTransparent) {
            // This call is expensive so don't call it unnecessarily.
            paint.reset();
        }
        setupPaintForStroking(&paint, &rect, 0);
        canvas()->drawRect(rect, paint);
    }
}
Example #16
0
// This method is only used to draw the little circles used in lists.
void GraphicsContext::drawEllipse(const IntRect& elipseRect)
{
    if (paintingDisabled())
        return;

    SkRect rect = elipseRect;
    if (!isRectSkiaSafe(getCTM(), rect))
        return;

    platformContext()->prepareForSoftwareDraw();
    SkPaint paint;
    platformContext()->setupPaintForFilling(&paint);
    platformContext()->canvas()->drawOval(rect, paint);

    if (strokeStyle() != NoStroke) {
        paint.reset();
        platformContext()->setupPaintForStroking(&paint, &rect, 0);
        platformContext()->canvas()->drawOval(rect, paint);
    }
}
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) {
    SkAutoCanvasRestore acr(canvas, true);

    SkPaint paint;
    SkScalar x = 0;
    const int scale = 32;

    paint.setAntiAlias(true);
    const char* name = gConfigNames[bm.config()];
    canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8,
                     paint);
    canvas->translate(SkIntToScalar(48), 0);

    canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale));
    
    x += draw_set(canvas, bm, 0, &paint);
    paint.reset();
    paint.setAlpha(0x80);
    draw_set(canvas, bm, x, &paint);
    return x * scale / 3;
}
Example #18
0
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) {
    SkAutoCanvasRestore acr(canvas, true);

    SkPaint paint;
    SkScalar x = 0;
    const int scale = 32;

    paint.setAntiAlias(true);
    sk_tool_utils::set_portable_typeface(&paint);
    const char* name = sk_tool_utils::colortype_name(bm.colorType());
    canvas->drawText(name, strlen(name), x, SkIntToScalar(bm.height())*scale*5/8,
                     paint);
    canvas->translate(SkIntToScalar(48), 0);

    canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale));

    x += draw_set(canvas, bm, 0, &paint);
    paint.reset();
    paint.setAlpha(0x80);
    draw_set(canvas, bm, x, &paint);
    return x * scale / 3;
}
static void test_backToFront(skiatest::Reporter* reporter) {
    SkLayerDrawLooper::Builder looperBuilder;
    SkLayerDrawLooper::LayerInfo layerInfo;

    // Add the back layer, with the defaults.
    (void)looperBuilder.addLayerOnTop(layerInfo);

    // Add the front layer, with some layer info set.
    layerInfo.fOffset.set(10.0f, 20.0f);
    layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
    SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
    layerPaint->setBlendMode(SkBlendMode::kSrc);

    FakeDevice device;
    SkCanvas canvas(&device);
    SkPaint paint;
    auto looper(looperBuilder.detach());
    SkArenaAlloc alloc{48};
    SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);

    // The back layer should come first.
    REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
    canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
    REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
    paint.reset();

    // Then the front layer.
    REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
    canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
    REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());

    // Only two layers were added, so that should be the end.
    REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
}
Example #20
0
static SkScalar draw_row(SkCanvas* canvas, const SkBitmap& bm) {
    SkAutoCanvasRestore acr(canvas, true);

    SkPaint paint;
    paint.setAntiAlias(true);

    SkScalar x = 0;
    const int scale = 32;

    SkFont      font(ToolUtils::create_portable_typeface());
    const char* name = ToolUtils::colortype_name(bm.colorType());
    canvas->drawString(name, x, SkIntToScalar(bm.height())*scale*5/8,
                       font, paint);
    canvas->translate(SkIntToScalar(48), 0);

    canvas->scale(SkIntToScalar(scale), SkIntToScalar(scale));

    x += draw_set(canvas, bm, 0, &paint);
    paint.reset();
    paint.setAlphaf(0.5f);
    draw_set(canvas, bm, x, &paint);
    return x * scale / 3;
}
// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
    if (paintingDisabled())
        return;

    SkPaint paint;
    SkRect r(rect);

    if (fillColor().alpha()) {
        m_data->setupPaintFill(&paint);
        GC2CANVAS(this)->drawRect(r, paint);
    }

    // According to GraphicsContext.h, stroking inside drawRect always means
    // a stroke of 1 inside the rect.
    if (strokeStyle() != NoStroke && strokeColor().alpha()) {
        paint.reset();
        m_data->setupPaintStroke(&paint, &r);
        paint.setPathEffect(0); // No dashing please
        paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
        r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
        GC2CANVAS(this)->drawRect(r, paint);
    }
}
bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
{
#if ENABLE(VIDEO)
    HTMLMediaElement* mediaElement = mediaElementParent(object->node());
    if (!mediaElement)
        return false;

    SkCanvas* canvas = paintInfo.context->platformContext()->canvas();
    SkRect backgroundRect;
    backgroundRect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());

    SkPaint paint;
    paint.setAntiAlias(true);

    // Draw the border of the time bar. The border only has one single color,
    // width and radius. So use the property of the left border.
    SkColor borderColor = object->style()->borderLeftColor().rgb();
    int borderWidth = object->style()->borderLeftWidth();
    IntSize borderRadius = object->style()->borderTopLeftRadius();
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(borderWidth);
    paint.setColor(borderColor);
    canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint);

    // Draw the background of the time bar.
    SkColor backgroundColor = object->style()->backgroundColor().rgb();
    paint.setStyle(SkPaint::kFill_Style);
    paint.setColor(backgroundColor);
    canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint);

    if (backgroundRect.width() >= 3 && backgroundRect.height() >= 3)
    {
        // Draw the buffered ranges.
        // FIXME: Draw multiple ranges if there are multiple buffered ranges.
        SkRect bufferedRect;
        bufferedRect.set(backgroundRect.fLeft + 2, backgroundRect.fTop + 2,
                         backgroundRect.fRight - 1, backgroundRect.fBottom - 1);
        int width = static_cast<int>(bufferedRect.width() * mediaElement->percentLoaded());
        bufferedRect.fRight = bufferedRect.fLeft + width;

        SkPoint points[2] = { { 0, bufferedRect.fTop }, { 0, bufferedRect.fBottom } };
        SkColor startColor = object->style()->color().rgb();
        SkColor endColor = SkColorSetRGB(SkColorGetR(startColor) / 2,
                                         SkColorGetG(startColor) / 2,
                                         SkColorGetB(startColor) / 2);
        SkColor colors[2] = { startColor, endColor };
        SkShader* gradient = SkGradientShader::CreateLinear(points, colors, 0,
                                                            sizeof(points) / sizeof(points[0]),
                                                            SkShader::kMirror_TileMode, 0);

        paint.reset();
        paint.setShader(gradient);
        paint.setAntiAlias(true);
        // Check for round rect with zero width or height, otherwise Skia will assert
        if (bufferedRect.width() > 0 && bufferedRect.height() > 0)
            canvas->drawRoundRect(bufferedRect, borderRadius.width(), borderRadius.height(), paint);
        gradient->unref();
    }
    return true;
#else
    UNUSED_PARAM(object);
    UNUSED_PARAM(paintInfo);
    UNUSED_PARAM(rect);
    return false;
#endif
}