/*
 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "platform/graphics/GraphicsContext.h"

#include "platform/TraceEvent.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/RoundedRect.h"
#include "platform/graphics/BitmapImage.h"
#include "platform/graphics/DisplayList.h"
#include "platform/graphics/Gradient.h"
#include "platform/graphics/ImageBuffer.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/text/BidiResolver.h"
#include "platform/text/TextRunIterator.h"
#include "platform/weborigin/KURL.h"
#include "third_party/skia/include/core/SkAnnotation.h"
#include "third_party/skia/include/core/SkClipStack.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkCornerPathEffect.h"
#include "third_party/skia/include/effects/SkLumaColorFilter.h"
#include "third_party/skia/include/effects/SkMatrixImageFilter.h"
#include "third_party/skia/include/effects/SkPictureImageFilter.h"
#include "third_party/skia/include/gpu/GrRenderTarget.h"
#include "third_party/skia/include/gpu/GrTexture.h"
#include "wtf/Assertions.h"
#include "wtf/MathExtras.h"

namespace blink {

namespace {

class CompatibleImageBufferSurface : public ImageBufferSurface {
    WTF_MAKE_NONCOPYABLE(CompatibleImageBufferSurface); WTF_MAKE_FAST_ALLOCATED;
public:
    CompatibleImageBufferSurface(PassRefPtr<SkSurface> surface, const IntSize& size, OpacityMode opacityMode)
        : ImageBufferSurface(size, opacityMode)
        , m_surface(surface)
    {
    }
    virtual ~CompatibleImageBufferSurface() { }

    virtual SkCanvas* canvas() const OVERRIDE { return m_surface ? m_surface->getCanvas() : 0; }
    virtual bool isValid() const OVERRIDE { return m_surface; }
    virtual bool isAccelerated() const OVERRIDE { return isValid() && m_surface->getCanvas()->getTopDevice()->accessRenderTarget(); }
    virtual Platform3DObject getBackingTexture() const OVERRIDE
    {
        ASSERT(isAccelerated());
        GrRenderTarget* renderTarget = m_surface->getCanvas()->getTopDevice()->accessRenderTarget();
        if (renderTarget) {
            return renderTarget->asTexture()->getTextureHandle();
        }
        return 0;
    };

private:
    RefPtr<SkSurface> m_surface;
};

} // unnamed namespace

struct GraphicsContext::CanvasSaveState {
    CanvasSaveState(bool pendingSave, int count)
        : m_pendingSave(pendingSave), m_restoreCount(count) { }

    bool m_pendingSave;
    int m_restoreCount;
};

struct GraphicsContext::RecordingState {
    RecordingState(SkCanvas* currentCanvas, const SkMatrix& currentMatrix, PassRefPtr<DisplayList> displayList)
        : m_savedCanvas(currentCanvas)
        , m_displayList(displayList)
        , m_savedMatrix(currentMatrix)
    {
    }

    SkCanvas* m_savedCanvas;
    RefPtr<DisplayList> m_displayList;
    const SkMatrix m_savedMatrix;
};

GraphicsContext::GraphicsContext(SkCanvas* canvas, DisabledMode disableContextOrPainting)
    : m_canvas(canvas)
    , m_paintStateStack()
    , m_paintStateIndex(0)
    , m_pendingCanvasSave(false)
    , m_annotationMode(0)
#if ENABLE(ASSERT)
    , m_annotationCount(0)
    , m_layerCount(0)
    , m_disableDestructionChecks(false)
#endif
    , m_disabledState(disableContextOrPainting)
    , m_deviceScaleFactor(1.0f)
    , m_regionTrackingMode(RegionTrackingDisabled)
    , m_trackTextRegion(false)
    , m_accelerated(false)
    , m_isCertainlyOpaque(true)
    , m_antialiasHairlineImages(false)
    , m_shouldSmoothFonts(true)
{
    ASSERT(canvas);

    // FIXME: Do some tests to determine how many states are typically used, and allocate
    // several here.
    m_paintStateStack.append(GraphicsContextState::create());
    m_paintState = m_paintStateStack.last().get();
}

GraphicsContext::~GraphicsContext()
{
#if ENABLE(ASSERT)
    if (!m_disableDestructionChecks) {
        ASSERT(!m_paintStateIndex);
        ASSERT(!m_paintState->saveCount());
        ASSERT(!m_annotationCount);
        ASSERT(!m_layerCount);
        ASSERT(m_recordingStateStack.isEmpty());
        ASSERT(m_canvasStateStack.isEmpty());
    }
#endif
}

void GraphicsContext::resetCanvas(SkCanvas* canvas)
{
    ASSERT(canvas);
    m_canvas = canvas;
    m_trackedRegion.reset();
}

void GraphicsContext::setRegionTrackingMode(RegionTrackingMode mode)
{
    m_regionTrackingMode = mode;
    if (mode == RegionTrackingOpaque)
        m_trackedRegion.setTrackedRegionType(RegionTracker::Opaque);
    else if (mode == RegionTrackingOverwrite)
        m_trackedRegion.setTrackedRegionType(RegionTracker::Overwrite);
}

void GraphicsContext::save()
{
    if (contextDisabled())
        return;

    m_paintState->incrementSaveCount();

    m_canvasStateStack.append(CanvasSaveState(m_pendingCanvasSave, m_canvas->getSaveCount()));
    m_pendingCanvasSave = true;
}

void GraphicsContext::restore()
{
    if (contextDisabled())
        return;

    if (!m_paintStateIndex && !m_paintState->saveCount()) {
        WTF_LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
        return;
    }

    if (m_paintState->saveCount()) {
        m_paintState->decrementSaveCount();
    } else {
        m_paintStateIndex--;
        m_paintState = m_paintStateStack[m_paintStateIndex].get();
    }

    CanvasSaveState savedState = m_canvasStateStack.last();
    m_canvasStateStack.removeLast();
    m_pendingCanvasSave = savedState.m_pendingSave;
    m_canvas->restoreToCount(savedState.m_restoreCount);
}

void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->saveLayer(bounds, paint);
    if (regionTrackingEnabled())
        m_trackedRegion.pushCanvasLayer(paint);
}

void GraphicsContext::restoreLayer()
{
    if (contextDisabled())
        return;

    m_canvas->restore();
    if (regionTrackingEnabled())
        m_trackedRegion.popCanvasLayer(this);
}

void GraphicsContext::beginAnnotation(const AnnotationList& annotations)
{
    if (contextDisabled())
        return;

    canvas()->beginCommentGroup("GraphicsContextAnnotation");

    AnnotationList::const_iterator end = annotations.end();
    for (AnnotationList::const_iterator it = annotations.begin(); it != end; ++it)
        canvas()->addComment(it->first, it->second.ascii().data());

#if ENABLE(ASSERT)
    ++m_annotationCount;
#endif
}

void GraphicsContext::endAnnotation()
{
    if (contextDisabled())
        return;

    ASSERT(m_annotationCount > 0);
    canvas()->endCommentGroup();

#if ENABLE(ASSERT)
    --m_annotationCount;
#endif
}

void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
    if (contextDisabled())
        return;

    ASSERT(pattern);
    if (!pattern) {
        setStrokeColor(Color::black);
        return;
    }
    mutableState()->setStrokePattern(pattern);
}

void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
{
    if (contextDisabled())
        return;

    ASSERT(gradient);
    if (!gradient) {
        setStrokeColor(Color::black);
        return;
    }
    mutableState()->setStrokeGradient(gradient);
}

void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
{
    if (contextDisabled())
        return;

    ASSERT(pattern);
    if (!pattern) {
        setFillColor(Color::black);
        return;
    }

    mutableState()->setFillPattern(pattern);
}

void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
{
    if (contextDisabled())
        return;

    ASSERT(gradient);
    if (!gradient) {
        setFillColor(Color::black);
        return;
    }

    mutableState()->setFillGradient(gradient);
}

void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color,
    DrawLooperBuilder::ShadowTransformMode shadowTransformMode,
    DrawLooperBuilder::ShadowAlphaMode shadowAlphaMode)
{
    if (contextDisabled())
        return;

    if (!color.alpha() || (!offset.width() && !offset.height() && !blur)) {
        clearShadow();
        return;
    }

    OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
    drawLooperBuilder->addShadow(offset, blur, color, shadowTransformMode, shadowAlphaMode);
    drawLooperBuilder->addUnmodifiedContent();
    setDrawLooper(drawLooperBuilder.release());
}

void GraphicsContext::setDrawLooper(PassOwnPtr<DrawLooperBuilder> drawLooperBuilder)
{
    if (contextDisabled())
        return;

    mutableState()->setDrawLooper(drawLooperBuilder->detachDrawLooper());
}

void GraphicsContext::clearDrawLooper()
{
    if (contextDisabled())
        return;

    mutableState()->clearDrawLooper();
}

bool GraphicsContext::hasShadow() const
{
    return !!immutableState()->drawLooper();
}

bool GraphicsContext::getTransformedClipBounds(FloatRect* bounds) const
{
    if (contextDisabled())
        return false;
    SkIRect skIBounds;
    if (!m_canvas->getClipDeviceBounds(&skIBounds))
        return false;
    SkRect skBounds = SkRect::Make(skIBounds);
    *bounds = FloatRect(skBounds);
    return true;
}

SkMatrix GraphicsContext::getTotalMatrix() const
{
    if (contextDisabled())
        return SkMatrix::I();

    if (!isRecording())
        return m_canvas->getTotalMatrix();

    const RecordingState& recordingState = m_recordingStateStack.last();
    SkMatrix totalMatrix = recordingState.m_savedMatrix;
    totalMatrix.preConcat(m_canvas->getTotalMatrix());

    return totalMatrix;
}

void GraphicsContext::adjustTextRenderMode(SkPaint* paint)
{
    if (contextDisabled())
        return;

    if (!paint->isLCDRenderText())
        return;

    paint->setLCDRenderText(couldUseLCDRenderedText());
}

bool GraphicsContext::couldUseLCDRenderedText()
{
    // Our layers only have a single alpha channel. This means that subpixel
    // rendered text cannot be composited correctly when the layer is
    // collapsed. Therefore, subpixel text is contextDisabled when we are drawing
    // onto a layer.
    if (contextDisabled() || m_canvas->isDrawingToLayer() || !isCertainlyOpaque())
        return false;

    return shouldSmoothFonts();
}

void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation, WebBlendMode blendMode)
{
    if (contextDisabled())
        return;
    mutableState()->setCompositeOperation(compositeOperation, blendMode);
}

SkColorFilter* GraphicsContext::colorFilter() const
{
    return immutableState()->colorFilter();
}

void GraphicsContext::setColorFilter(ColorFilter colorFilter)
{
    GraphicsContextState* stateToSet = mutableState();

    // We only support one active color filter at the moment. If (when) this becomes a problem,
    // we should switch to using color filter chains (Skia work in progress).
    ASSERT(!stateToSet->colorFilter());
    stateToSet->setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter));
}

bool GraphicsContext::readPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, int x, int y)
{
    if (contextDisabled())
        return false;

    return m_canvas->readPixels(info, pixels, rowBytes, x, y);
}

void GraphicsContext::setMatrix(const SkMatrix& matrix)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->setMatrix(matrix);
}

void GraphicsContext::concat(const SkMatrix& matrix)
{
    if (contextDisabled())
        return;

    if (matrix.isIdentity())
        return;

    realizeCanvasSave();

    m_canvas->concat(matrix);
}

void GraphicsContext::beginTransparencyLayer(float opacity, const FloatRect* bounds)
{
    beginLayer(opacity, immutableState()->compositeOperator(), bounds);
}

void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const FloatRect* bounds, ColorFilter colorFilter, ImageFilter* imageFilter)
{
    if (contextDisabled())
        return;

    SkPaint layerPaint;
    layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255));
    layerPaint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op, m_paintState->blendMode()));
    layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).get());
    layerPaint.setImageFilter(imageFilter);

    if (bounds) {
        SkRect skBounds = WebCoreFloatRectToSKRect(*bounds);
        saveLayer(&skBounds, &layerPaint);
    } else {
        saveLayer(0, &layerPaint);
    }

#if ENABLE(ASSERT)
    ++m_layerCount;
#endif
}

void GraphicsContext::endLayer()
{
    if (contextDisabled())
        return;

    restoreLayer();

    ASSERT(m_layerCount > 0);
#if ENABLE(ASSERT)
    --m_layerCount;
#endif
}

void GraphicsContext::beginRecording(const FloatRect& bounds)
{
    RefPtr<DisplayList> displayList = adoptRef(new DisplayList(bounds));

    SkCanvas* savedCanvas = m_canvas;
    SkMatrix savedMatrix = getTotalMatrix();

    if (!contextDisabled()) {
        IntRect recordingRect = enclosingIntRect(bounds);
        m_canvas = displayList->beginRecording(recordingRect.size());

        // We want the bounds offset mapped to (0, 0), such that the display list content
        // is fully contained within the SkPictureRecord's bounds.
        if (!toFloatSize(bounds.location()).isZero()) {
            m_canvas->translate(-bounds.x(), -bounds.y());
            // To avoid applying the offset repeatedly in getTotalMatrix(), we pre-apply it here.
            savedMatrix.preTranslate(bounds.x(), bounds.y());
        }
    }

    m_recordingStateStack.append(RecordingState(savedCanvas, savedMatrix, displayList));
}

PassRefPtr<DisplayList> GraphicsContext::endRecording()
{
    ASSERT(!m_recordingStateStack.isEmpty());

    RecordingState recording = m_recordingStateStack.last();
    if (!contextDisabled()) {
        ASSERT(recording.m_displayList->isRecording());
        recording.m_displayList->endRecording();
    }

    m_recordingStateStack.removeLast();
    m_canvas = recording.m_savedCanvas;

    return recording.m_displayList.release();
}

bool GraphicsContext::isRecording() const
{
    return !m_recordingStateStack.isEmpty();
}

void GraphicsContext::drawDisplayList(DisplayList* displayList)
{
    ASSERT(displayList);
    ASSERT(!displayList->isRecording());

    if (contextDisabled() || displayList->bounds().isEmpty())
        return;

    realizeCanvasSave();

    const FloatRect& bounds = displayList->bounds();
    if (bounds.x() || bounds.y()) {
        SkMatrix m;
        m.setTranslate(bounds.x(), bounds.y());
        m_canvas->drawPicture(displayList->picture(), &m, 0);
    } else {
        m_canvas->drawPicture(displayList->picture());
    }
}

void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
{
    if (contextDisabled())
        return;

    if (numPoints <= 1)
        return;

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

    SkPaint paint(immutableState()->fillPaint());
    paint.setAntiAlias(shouldAntialias);
    drawPath(path, paint);

    if (strokeStyle() != NoStroke)
        drawPath(path, immutableState()->strokePaint());
}

float GraphicsContext::prepareFocusRingPaint(SkPaint& paint, const Color& color, int width) const
{
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(color.rgb());
    paint.setStrokeWidth(focusRingWidth(width));

#if OS(MACOSX)
    paint.setAlpha(64);
    return (width - 1) * 0.5f;
#else
    return 1;
#endif
}

void GraphicsContext::drawFocusRingPath(const SkPath& path, const Color& color, int width)
{
    SkPaint paint;
    float cornerRadius = prepareFocusRingPaint(paint, color, width);

    paint.setPathEffect(SkCornerPathEffect::Create(SkFloatToScalar(cornerRadius)))->unref();

    // Outer path
    drawPath(path, paint);

#if OS(MACOSX)
    // Inner path
    paint.setAlpha(128);
    paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f);
    drawPath(path, paint);
#endif
}

void GraphicsContext::drawFocusRingRect(const SkRect& rect, const Color& color, int width)
{
    SkPaint paint;
    float cornerRadius = prepareFocusRingPaint(paint, color, width);

    SkRRect rrect;
    rrect.setRectXY(rect, SkFloatToScalar(cornerRadius), SkFloatToScalar(cornerRadius));

    // Outer rect
    drawRRect(rrect, paint);

#if OS(MACOSX)
    // Inner rect
    paint.setAlpha(128);
    paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f);
    drawRRect(rrect, paint);
#endif
}

void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int offset, const Color& color)
{
    // FIXME: Implement support for offset.
    if (contextDisabled())
        return;

    drawFocusRingPath(focusRingPath.skPath(), color, width);
}

void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
{
    if (contextDisabled())
        return;

    unsigned rectCount = rects.size();
    if (!rectCount)
        return;

    SkRegion focusRingRegion;
    const int outset = focusRingOutset(offset);
    for (unsigned i = 0; i < rectCount; i++) {
        SkIRect r = rects[i];
        r.inset(-outset, -outset);
        focusRingRegion.op(r, SkRegion::kUnion_Op);
    }

    if (focusRingRegion.isRect()) {
        drawFocusRingRect(SkRect::MakeFromIRect(focusRingRegion.getBounds()), color, width);
    } else {
        SkPath path;
        if (focusRingRegion.getBoundaryPath(&path))
            drawFocusRingPath(path, color, width);
    }
}

static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset)
{
    IntRect bounds(holeRect);

    bounds.inflate(shadowBlur);

    if (shadowSpread < 0)
        bounds.inflate(-shadowSpread);

    IntRect offsetBounds = bounds;
    offsetBounds.move(-shadowOffset);
    return unionRect(bounds, offsetBounds);
}

void GraphicsContext::drawInnerShadow(const RoundedRect& rect, const Color& shadowColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges clippedEdges)
{
    if (contextDisabled())
        return;

    IntRect holeRect(rect.rect());
    holeRect.inflate(-shadowSpread);

    if (holeRect.isEmpty()) {
        if (rect.isRounded())
            fillRoundedRect(rect, shadowColor);
        else
            fillRect(rect.rect(), shadowColor);
        return;
    }

    if (clippedEdges & LeftEdge) {
        holeRect.move(-std::max(shadowOffset.width(), 0) - shadowBlur, 0);
        holeRect.setWidth(holeRect.width() + std::max(shadowOffset.width(), 0) + shadowBlur);
    }
    if (clippedEdges & TopEdge) {
        holeRect.move(0, -std::max(shadowOffset.height(), 0) - shadowBlur);
        holeRect.setHeight(holeRect.height() + std::max(shadowOffset.height(), 0) + shadowBlur);
    }
    if (clippedEdges & RightEdge)
        holeRect.setWidth(holeRect.width() - std::min(shadowOffset.width(), 0) + shadowBlur);
    if (clippedEdges & BottomEdge)
        holeRect.setHeight(holeRect.height() - std::min(shadowOffset.height(), 0) + shadowBlur);

    Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);

    IntRect outerRect = areaCastingShadowInHole(rect.rect(), shadowBlur, shadowSpread, shadowOffset);
    RoundedRect roundedHole(holeRect, rect.radii());

    save();
    if (rect.isRounded()) {
        Path path;
        path.addRoundedRect(rect);
        clipPath(path);
        roundedHole.shrinkRadii(shadowSpread);
    } else {
        clip(rect.rect());
    }

    OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create();
    drawLooperBuilder->addShadow(shadowOffset, shadowBlur, shadowColor,
        DrawLooperBuilder::ShadowRespectsTransforms, DrawLooperBuilder::ShadowIgnoresAlpha);
    setDrawLooper(drawLooperBuilder.release());
    fillRectWithRoundedHole(outerRect, roundedHole, fillColor);
    restore();
    clearDrawLooper();
}

void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
    if (contextDisabled())
        return;

    StrokeStyle penStyle = strokeStyle();
    if (penStyle == NoStroke)
        return;

    FloatPoint p1 = point1;
    FloatPoint p2 = point2;
    bool isVerticalLine = (p1.x() == p2.x());
    int width = roundf(strokeThickness());

    // We know these are vertical or horizontal lines, so the length will just
    // be the sum of the displacement component vectors give or take 1 -
    // probably worth the speed up of no square root, which also won't be exact.
    FloatSize disp = p2 - p1;
    int length = SkScalarRoundToInt(disp.width() + disp.height());
    SkPaint paint(immutableState()->strokePaint(length));

    if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
        // Do a rect fill of our endpoints.  This ensures we always have the
        // appearance of being a border.  We then draw the actual dotted/dashed line.
        SkRect r1, r2;
        r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width);
        r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width);

        if (isVerticalLine) {
            r1.offset(-width / 2, 0);
            r2.offset(-width / 2, -width);
        } else {
            r1.offset(0, -width / 2);
            r2.offset(-width, -width / 2);
        }
        SkPaint fillPaint;
        fillPaint.setColor(paint.getColor());
        drawRect(r1, fillPaint);
        drawRect(r2, fillPaint);
    }

    adjustLineToPixelBoundaries(p1, p2, width, penStyle);
    SkPoint pts[2] = { p1.data(), p2.data() };

    m_canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawPoints(this, SkCanvas::kLines_PointMode, 2, pts, paint);
}

void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float width, DocumentMarkerLineStyle style)
{
    if (contextDisabled())
        return;

    // Use 2x resources for a device scale factor of 1.5 or above.
    int deviceScaleFactor = m_deviceScaleFactor > 1.5f ? 2 : 1;

    // Create the pattern we'll use to draw the underline.
    int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0;
    static SkBitmap* misspellBitmap1x[2] = { 0, 0 };
    static SkBitmap* misspellBitmap2x[2] = { 0, 0 };
    SkBitmap** misspellBitmap = deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x;
    if (!misspellBitmap[index]) {
#if OS(MACOSX)
        // Match the artwork used by the Mac.
        const int rowPixels = 4 * deviceScaleFactor;
        const int colPixels = 3 * deviceScaleFactor;
        SkBitmap bitmap;
        bitmap.allocN32Pixels(rowPixels, colPixels);

        bitmap.eraseARGB(0, 0, 0, 0);
        const uint32_t transparentColor = 0x00000000;

        if (deviceScaleFactor == 1) {
            const uint32_t colors[2][6] = {
                { 0x2a2a0600, 0x57571000,  0xa8a81b00, 0xbfbf1f00,  0x70701200, 0xe0e02400 },
                { 0x2a0f0f0f, 0x571e1e1e,  0xa83d3d3d, 0xbf454545,  0x70282828, 0xe0515151 }
            };

            // Pattern: a b a   a b a
            //          c d c   c d c
            //          e f e   e f e
            for (int x = 0; x < colPixels; ++x) {
                uint32_t* row = bitmap.getAddr32(0, x);
                row[0] = colors[index][x * 2];
                row[1] = colors[index][x * 2 + 1];
                row[2] = colors[index][x * 2];
                row[3] = transparentColor;
            }
        } else if (deviceScaleFactor == 2) {
            const uint32_t colors[2][18] = {
                { 0x0a090101, 0x33320806, 0x55540f0a,  0x37360906, 0x6e6c120c, 0x6e6c120c,  0x7674140d, 0x8d8b1810, 0x8d8b1810,
                  0x96941a11, 0xb3b01f15, 0xb3b01f15,  0x6d6b130c, 0xd9d62619, 0xd9d62619,  0x19180402, 0x7c7a150e, 0xcecb2418 },
                { 0x0a020202, 0x33141414, 0x55232323,  0x37161616, 0x6e2e2e2e, 0x6e2e2e2e,  0x76313131, 0x8d3a3a3a, 0x8d3a3a3a,
                  0x963e3e3e, 0xb34b4b4b, 0xb34b4b4b,  0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b,  0x19090909, 0x7c343434, 0xce575757 }
            };

            // Pattern: a b c c b a
            //          d e f f e d
            //          g h j j h g
            //          k l m m l k
            //          n o p p o n
            //          q r s s r q
            for (int x = 0; x < colPixels; ++x) {
                uint32_t* row = bitmap.getAddr32(0, x);
                row[0] = colors[index][x * 3];
                row[1] = colors[index][x * 3 + 1];
                row[2] = colors[index][x * 3 + 2];
                row[3] = colors[index][x * 3 + 2];
                row[4] = colors[index][x * 3 + 1];
                row[5] = colors[index][x * 3];
                row[6] = transparentColor;
                row[7] = transparentColor;
            }
        } else
            ASSERT_NOT_REACHED();

        misspellBitmap[index] = new SkBitmap(bitmap);
#else
        // We use a 2-pixel-high misspelling indicator because that seems to be
        // what WebKit is designed for, and how much room there is in a typical
        // page for it.
        const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below.
        const int colPixels = 2 * deviceScaleFactor;
        SkBitmap bitmap;
        bitmap.allocN32Pixels(rowPixels, colPixels);

        bitmap.eraseARGB(0, 0, 0, 0);
        if (deviceScaleFactor == 1)
            draw1xMarker(&bitmap, index);
        else if (deviceScaleFactor == 2)
            draw2xMarker(&bitmap, index);
        else
            ASSERT_NOT_REACHED();

        misspellBitmap[index] = new SkBitmap(bitmap);
#endif
    }

#if OS(MACOSX)
    SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor;
    SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor;

    // Make sure to draw only complete dots.
    int rowPixels = misspellBitmap[index]->width();
    float widthMod = fmodf(width * deviceScaleFactor, rowPixels);
    if (rowPixels - widthMod > deviceScaleFactor)
        width -= widthMod / deviceScaleFactor;
#else
    SkScalar originX = WebCoreFloatToSkScalar(pt.x());

    // Offset it vertically by 1 so that there's some space under the text.
    SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
    originX *= deviceScaleFactor;
    originY *= deviceScaleFactor;
#endif

    SkMatrix localMatrix;
    localMatrix.setTranslate(originX, originY);
    RefPtr<SkShader> shader = adoptRef(SkShader::CreateBitmapShader(
        *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix));

    SkPaint paint;
    paint.setShader(shader.get());

    SkRect rect;
    rect.set(originX, originY, originX + WebCoreFloatToSkScalar(width) * deviceScaleFactor, originY + SkIntToScalar(misspellBitmap[index]->height()));

    if (deviceScaleFactor == 2) {
        save();
        scale(0.5, 0.5);
    }
    drawRect(rect, paint);
    if (deviceScaleFactor == 2)
        restore();
}

void GraphicsContext::drawLineForText(const FloatPoint& pt, float width)
{
    if (contextDisabled())
        return;

    if (width <= 0)
        return;

    SkPaint paint;
    switch (strokeStyle()) {
    case NoStroke:
    case SolidStroke:
    case DoubleStroke:
    case WavyStroke: {
        int thickness = SkMax32(static_cast<int>(strokeThickness()), 1);
        SkRect r;
        r.fLeft = WebCoreFloatToSkScalar(pt.x());
        // Avoid anti-aliasing lines. Currently, these are always horizontal.
        // Round to nearest pixel to match text and other content.
        r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f));
        r.fRight = r.fLeft + WebCoreFloatToSkScalar(width);
        r.fBottom = r.fTop + SkIntToScalar(thickness);
        paint = immutableState()->fillPaint();
        // Text lines are drawn using the stroke color.
        paint.setColor(effectiveStrokeColor());
        drawRect(r, paint);
        return;
    }
    case DottedStroke:
    case DashedStroke: {
        int y = floorf(pt.y() + std::max<float>(strokeThickness() / 2.0f, 0.5f));
        drawLine(IntPoint(pt.x(), y), IntPoint(pt.x() + width, y));
        return;
    }
    }

    ASSERT_NOT_REACHED();
}

// Draws a filled rectangle with a stroked border.
void GraphicsContext::drawRect(const IntRect& rect)
{
    if (contextDisabled())
        return;

    ASSERT(!rect.isEmpty());
    if (rect.isEmpty())
        return;

    SkRect skRect = rect;
    int fillcolorNotTransparent = immutableState()->fillColor().rgb() & 0xFF000000;
    if (fillcolorNotTransparent)
        drawRect(skRect, immutableState()->fillPaint());

    if (immutableState()->strokeData().style() != NoStroke
        && immutableState()->strokeData().color().alpha()) {
        // Stroke a width: 1 inset border
        SkPaint paint(immutableState()->fillPaint());
        paint.setColor(effectiveStrokeColor());
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(1);

        skRect.inset(0.5f, 0.5f);
        drawRect(skRect, paint);
    }
}

void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point)
{
    if (contextDisabled())
        return;

    font.drawText(this, runInfo, point);
}

void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point)
{
    if (contextDisabled())
        return;

    font.drawEmphasisMarks(this, runInfo, mark, point);
}

void GraphicsContext::drawBidiText(const Font& font, const TextRunPaintInfo& runInfo, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReadyAction)
{
    if (contextDisabled())
        return;

    // sub-run painting is not supported for Bidi text.
    const TextRun& run = runInfo.run;
    ASSERT((runInfo.from == 0) && (runInfo.to == run.length()));
    BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
    bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()));
    bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0));

    // FIXME: This ownership should be reversed. We should pass BidiRunList
    // to BidiResolver in createBidiRunsForLine.
    BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
    bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
    if (!bidiRuns.runCount())
        return;

    FloatPoint currPoint = point;
    BidiCharacterRun* bidiRun = bidiRuns.firstRun();
    while (bidiRun) {
        TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun->start());
        bool isRTL = bidiRun->level() % 2;
        subrun.setDirection(isRTL ? RTL : LTR);
        subrun.setDirectionalOverride(bidiRun->dirOverride());

        TextRunPaintInfo subrunInfo(subrun);
        subrunInfo.bounds = runInfo.bounds;
        font.drawText(this, subrunInfo, currPoint, customFontNotReadyAction);

        bidiRun = bidiRun->next();
        // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
        if (bidiRun)
            currPoint.move(font.width(subrun), 0);
    }

    bidiRuns.deleteRuns();
}

void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, int from, int to)
{
    if (contextDisabled())
        return;

    fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor);
}

void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
    if (!image)
        return;
    drawImage(image, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation);
}

void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
    if (!image)
        return;
    drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size())), op, shouldRespectImageOrientation);
}

void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageOrientation)
{
    drawImage(image, dest, src, op, WebBlendModeNormal, shouldRespectImageOrientation);
}

void GraphicsContext::drawImage(Image* image, const FloatRect& dest)
{
    if (!image)
        return;
    drawImage(image, dest, FloatRect(IntRect(IntPoint(), image->size())));
}

void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, RespectImageOrientationEnum shouldRespectImageOrientation)
{
    if (contextDisabled() || !image)
        return;
    image->draw(this, dest, src, op, blendMode, shouldRespectImageOrientation);
}

void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, WebBlendMode blendMode, const IntSize& repeatSpacing)
{
    if (contextDisabled() || !image)
        return;
    image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repeatSpacing);
}

void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect,
    const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
{
    if (contextDisabled() || !image)
        return;

    if (hRule == Image::StretchTile && vRule == Image::StretchTile) {
        // Just do a scale.
        drawImage(image, dest, srcRect, op);
        return;
    }

    image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op);
}

void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest,
    const FloatRect* src, CompositeOperator op, WebBlendMode blendMode)
{
    if (contextDisabled() || !image)
        return;

    image->draw(this, dest, src, op, blendMode);
}

void GraphicsContext::drawPicture(PassRefPtr<SkPicture> picture, const FloatRect& dest, const FloatRect& src, CompositeOperator op, WebBlendMode blendMode)
{
    if (contextDisabled() || !picture)
        return;

    SkMatrix ctm = m_canvas->getTotalMatrix();
    SkRect deviceDest;
    ctm.mapRect(&deviceDest, dest);
    SkRect sourceBounds = WebCoreFloatRectToSKRect(src);

    RefPtr<SkPictureImageFilter> pictureFilter = adoptRef(SkPictureImageFilter::Create(picture.get(), sourceBounds));
    SkMatrix layerScale;
    layerScale.setScale(deviceDest.width() / src.width(), deviceDest.height() / src.height());
    RefPtr<SkMatrixImageFilter> matrixFilter = adoptRef(SkMatrixImageFilter::Create(layerScale, SkPaint::kLow_FilterLevel, pictureFilter.get()));
    SkPaint picturePaint;
    picturePaint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op, blendMode));
    picturePaint.setImageFilter(matrixFilter.get());
    SkRect layerBounds = SkRect::MakeWH(std::max(deviceDest.width(), sourceBounds.width()), std::max(deviceDest.height(), sourceBounds.height()));
    m_canvas->save();
    m_canvas->resetMatrix();
    m_canvas->translate(deviceDest.x(), deviceDest.y());
    m_canvas->saveLayer(&layerBounds, &picturePaint);
    m_canvas->restore();
    m_canvas->restore();
}

void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
{
    if (contextDisabled())
        return;

    m_canvas->writePixels(info, pixels, rowBytes, x, y);

    if (regionTrackingEnabled()) {
        SkRect rect = SkRect::MakeXYWH(x, y, info.width(), info.height());
        SkPaint paint;

        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
        if (kOpaque_SkAlphaType != info.alphaType())
            paint.setAlpha(0x80); // signal to m_trackedRegion that we are not fully opaque

        m_trackedRegion.didDrawRect(this, rect, paint, 0);
        // more efficient would be to call markRectAsOpaque or MarkRectAsNonOpaque directly,
        // rather than cons-ing up a paint with an xfermode and alpha
    }
}

void GraphicsContext::writePixels(const SkBitmap& bitmap, int x, int y)
{
    if (contextDisabled())
        return;

    if (!bitmap.getTexture()) {
        SkAutoLockPixels alp(bitmap);
        if (bitmap.getPixels())
            writePixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), x, y);
    }
}

void GraphicsContext::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, const SkPaint* paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawBitmap(bitmap, left, top, paint);

    if (regionTrackingEnabled()) {
        SkRect rect = SkRect::MakeXYWH(left, top, bitmap.width(), bitmap.height());
        m_trackedRegion.didDrawRect(this, rect, *paint, &bitmap);
    }
}

void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
    const SkRect& dst, const SkPaint* paint)
{
    if (contextDisabled())
        return;

    SkCanvas::DrawBitmapRectFlags flags =
        immutableState()->shouldClampToSourceRect() ? SkCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag;

    m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawRect(this, dst, *paint, &bitmap);
}

void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawOval(oval, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawBounded(this, oval, paint);
}

void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawPath(path, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawPath(this, path, paint);
}

void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawRect(rect, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawRect(this, rect, paint, 0);
}

void GraphicsContext::drawRRect(const SkRRect& rrect, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawRRect(rrect, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawBounded(this, rrect.rect(), paint);
}

void GraphicsContext::didDrawRect(const SkRect& rect, const SkPaint& paint, const SkBitmap* bitmap)
{
    if (contextDisabled())
        return;

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawRect(this, rect, paint, bitmap);
}

void GraphicsContext::drawPosText(const void* text, size_t byteLength,
    const SkPoint pos[], const SkRect& textRect, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawPosText(text, byteLength, pos, paint);
    didDrawTextInRect(textRect);

    // FIXME: compute bounds for positioned text.
    if (regionTrackingEnabled())
        m_trackedRegion.didDrawUnbounded(this, paint, RegionTracker::FillOrStroke);
}

void GraphicsContext::drawPosTextH(const void* text, size_t byteLength,
    const SkScalar xpos[], SkScalar constY, const SkRect& textRect, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawPosTextH(text, byteLength, xpos, constY, paint);
    didDrawTextInRect(textRect);

    // FIXME: compute bounds for positioned text.
    if (regionTrackingEnabled())
        m_trackedRegion.didDrawUnbounded(this, paint, RegionTracker::FillOrStroke);
}

void GraphicsContext::drawTextBlob(const SkTextBlob* blob, const SkPoint& origin, const SkPaint& paint)
{
    if (contextDisabled())
        return;

    m_canvas->drawTextBlob(blob, origin.x(), origin.y(), paint);

    SkRect bounds = blob->bounds();
    bounds.offset(origin);
    didDrawTextInRect(bounds);

    // FIXME: use bounds here if it helps performance.
    if (regionTrackingEnabled())
        m_trackedRegion.didDrawUnbounded(this, paint, RegionTracker::FillOrStroke);
}

void GraphicsContext::fillPath(const Path& pathToFill)
{
    if (contextDisabled() || pathToFill.isEmpty())
        return;

    // Use const_cast and temporarily modify the fill type instead of copying the path.
    SkPath& path = const_cast<SkPath&>(pathToFill.skPath());
    SkPath::FillType previousFillType = path.getFillType();

    SkPath::FillType temporaryFillType = WebCoreWindRuleToSkFillType(immutableState()->fillRule());
    path.setFillType(temporaryFillType);

    drawPath(path, immutableState()->fillPaint());

    path.setFillType(previousFillType);
}

void GraphicsContext::fillRect(const FloatRect& rect)
{
    if (contextDisabled())
        return;

    SkRect r = rect;

    drawRect(r, immutableState()->fillPaint());
}

void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
{
    if (contextDisabled())
        return;

    SkRect r = rect;
    SkPaint paint = immutableState()->fillPaint();
    paint.setColor(color.rgb());
    drawRect(r, paint);
}

void GraphicsContext::fillBetweenRoundedRects(const IntRect& outer, const IntSize& outerTopLeft, const IntSize& outerTopRight, const IntSize& outerBottomLeft, const IntSize& outerBottomRight,
    const IntRect& inner, const IntSize& innerTopLeft, const IntSize& innerTopRight, const IntSize& innerBottomLeft, const IntSize& innerBottomRight, const Color& color) {
    if (contextDisabled())
        return;

    SkVector outerRadii[4];
    SkVector innerRadii[4];
    setRadii(outerRadii, outerTopLeft, outerTopRight, outerBottomRight, outerBottomLeft);
    setRadii(innerRadii, innerTopLeft, innerTopRight, innerBottomRight, innerBottomLeft);

    SkRRect rrOuter;
    SkRRect rrInner;
    rrOuter.setRectRadii(outer, outerRadii);
    rrInner.setRectRadii(inner, innerRadii);

    SkPaint paint(immutableState()->fillPaint());
    paint.setColor(color.rgb());

    m_canvas->drawDRRect(rrOuter, rrInner, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawBounded(this, rrOuter.getBounds(), paint);
}

void GraphicsContext::fillBetweenRoundedRects(const RoundedRect& outer, const RoundedRect& inner, const Color& color)
{
    fillBetweenRoundedRects(outer.rect(), outer.radii().topLeft(), outer.radii().topRight(), outer.radii().bottomLeft(), outer.radii().bottomRight(),
        inner.rect(), inner.radii().topLeft(), inner.radii().topRight(), inner.radii().bottomLeft(), inner.radii().bottomRight(), color);
}

void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
    const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
{
    if (contextDisabled())
        return;

    if (topLeft.width() + topRight.width() > rect.width()
            || bottomLeft.width() + bottomRight.width() > rect.width()
            || topLeft.height() + bottomLeft.height() > rect.height()
            || topRight.height() + bottomRight.height() > rect.height()) {
        // Not all the radii fit, return a rect. This matches the behavior of
        // Path::createRoundedRectangle. Without this we attempt to draw a round
        // shadow for a square box.
        fillRect(rect, color);
        return;
    }

    SkVector radii[4];
    setRadii(radii, topLeft, topRight, bottomRight, bottomLeft);

    SkRRect rr;
    rr.setRectRadii(rect, radii);

    SkPaint paint(immutableState()->fillPaint());
    paint.setColor(color.rgb());

    m_canvas->drawRRect(rr, paint);

    if (regionTrackingEnabled())
        m_trackedRegion.didDrawBounded(this, rr.getBounds(), paint);
}

void GraphicsContext::fillEllipse(const FloatRect& ellipse)
{
    if (contextDisabled())
        return;

    SkRect rect = ellipse;
    drawOval(rect, immutableState()->fillPaint());
}

void GraphicsContext::strokePath(const Path& pathToStroke)
{
    if (contextDisabled() || pathToStroke.isEmpty())
        return;

    const SkPath& path = pathToStroke.skPath();
    drawPath(path, immutableState()->strokePaint());
}

void GraphicsContext::strokeRect(const FloatRect& rect)
{
    strokeRect(rect, strokeThickness());
}

void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
    if (contextDisabled())
        return;

    SkPaint paint(immutableState()->strokePaint());
    paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth));
    // Reset the dash effect to account for the width
    immutableState()->strokeData().setupPaintDashPathEffect(&paint, 0);
    // strokerect has special rules for CSS when the rect is degenerate:
    // if width==0 && height==0, do nothing
    // if width==0 || height==0, then just draw line for the other dimension
    SkRect r(rect);
    bool validW = r.width() > 0;
    bool validH = r.height() > 0;
    if (validW && validH) {
        drawRect(r, paint);
    } else if (validW || validH) {
        // we are expected to respect the lineJoin, so we can't just call
        // drawLine -- we have to create a path that doubles back on itself.
        SkPath path;
        path.moveTo(r.fLeft, r.fTop);
        path.lineTo(r.fRight, r.fBottom);
        path.close();
        drawPath(path, paint);
    }
}

void GraphicsContext::strokeEllipse(const FloatRect& ellipse)
{
    if (contextDisabled())
        return;

    drawOval(ellipse, immutableState()->strokePaint());
}

void GraphicsContext::clipRoundedRect(const RoundedRect& rect, SkRegion::Op regionOp)
{
    if (contextDisabled())
        return;

    if (!rect.isRounded()) {
        clipRect(rect.rect(), NotAntiAliased, regionOp);
        return;
    }

    SkVector radii[4];
    RoundedRect::Radii wkRadii = rect.radii();
    setRadii(radii, wkRadii.topLeft(), wkRadii.topRight(), wkRadii.bottomRight(), wkRadii.bottomLeft());

    SkRRect r;
    r.setRectRadii(rect.rect(), radii);

    clipRRect(r, AntiAliased, regionOp);
}

void GraphicsContext::clipOut(const Path& pathToClip)
{
    if (contextDisabled())
        return;

    // Use const_cast and temporarily toggle the inverse fill type instead of copying the path.
    SkPath& path = const_cast<SkPath&>(pathToClip.skPath());
    path.toggleInverseFillType();
    clipPath(path, AntiAliased);
    path.toggleInverseFillType();
}

void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
{
    if (contextDisabled() || pathToClip.isEmpty())
        return;

    // Use const_cast and temporarily modify the fill type instead of copying the path.
    SkPath& path = const_cast<SkPath&>(pathToClip.skPath());
    SkPath::FillType previousFillType = path.getFillType();

    SkPath::FillType temporaryFillType = WebCoreWindRuleToSkFillType(clipRule);
    path.setFillType(temporaryFillType);
    clipPath(path, AntiAliased);

    path.setFillType(previousFillType);
}

void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialiased)
{
    if (contextDisabled())
        return;

    if (numPoints <= 1)
        return;

    SkPath path;
    setPathFromConvexPoints(&path, numPoints, points);
    clipPath(path, antialiased ? AntiAliased : NotAntiAliased);
}

void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect)
{
    if (contextDisabled())
        return;

    clipRoundedRect(rect, SkRegion::kDifference_Op);
}

void GraphicsContext::canvasClip(const Path& pathToClip, WindRule clipRule)
{
    if (contextDisabled())
        return;

    // Use const_cast and temporarily modify the fill type instead of copying the path.
    SkPath& path = const_cast<SkPath&>(pathToClip.skPath());
    SkPath::FillType previousFillType = path.getFillType();

    SkPath::FillType temporaryFillType = WebCoreWindRuleToSkFillType(clipRule);
    path.setFillType(temporaryFillType);
    clipPath(path);

    path.setFillType(previousFillType);
}

void GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion::Op op)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->clipRect(rect, op, aa == AntiAliased);
}

void GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion::Op op)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->clipPath(path, op, aa == AntiAliased);
}

void GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegion::Op op)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->clipRRect(rect, op, aa == AntiAliased);
}

void GraphicsContext::beginCull(const FloatRect& rect)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();
    m_canvas->pushCull(rect);
}

void GraphicsContext::endCull()
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->popCull();
}

void GraphicsContext::rotate(float angleInRadians)
{
    if (contextDisabled())
        return;

    realizeCanvasSave();

    m_canvas->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.14159265f)));
}

void GraphicsContext::translate(float x, float y)
{
    if (contextDisabled())
        return;

    if (!x && !y)
        return;

    realizeCanvasSave();

    m_canvas->translate(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}

void GraphicsContext::scale(float x, float y)
{
    if (contextDisabled())
        return;

    if (x == 1.0f && y == 1.0f)
        return;

    realizeCanvasSave();

    m_canvas->scale(WebCoreFloatToSkScalar(x), WebCoreFloatToSkScalar(y));
}

void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
    if (contextDisabled())
        return;

    SkAutoDataUnref url(SkData::NewWithCString(link.string().utf8().data()));
    SkAnnotateRectWithURL(m_canvas, destRect, url.get());
}

void GraphicsContext::setURLFragmentForRect(const String& destName, const IntRect& rect)
{
    if (contextDisabled())
        return;

    SkAutoDataUnref skDestName(SkData::NewWithCString(destName.utf8().data()));
    SkAnnotateLinkToDestination(m_canvas, rect, skDestName.get());
}

void GraphicsContext::addURLTargetAtPoint(const String& name, const IntPoint& pos)
{
    if (contextDisabled())
        return;

    SkAutoDataUnref nameData(SkData::NewWithCString(name.utf8().data()));
    SkAnnotateNamedDestination(m_canvas, SkPoint::Make(pos.x(), pos.y()), nameData);
}

AffineTransform GraphicsContext::getCTM() const
{
    if (contextDisabled())
        return AffineTransform();

    SkMatrix m = getTotalMatrix();
    return AffineTransform(SkScalarToDouble(m.getScaleX()),
                           SkScalarToDouble(m.getSkewY()),
                           SkScalarToDouble(m.getSkewX()),
                           SkScalarToDouble(m.getScaleY()),
                           SkScalarToDouble(m.getTranslateX()),
                           SkScalarToDouble(m.getTranslateY()));
}

void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op)
{
    if (contextDisabled())
        return;

    CompositeOperator previousOperator = compositeOperation();
    setCompositeOperation(op);
    fillRect(rect, color);
    setCompositeOperation(previousOperator);
}

void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& color)
{
    if (contextDisabled())
        return;

    if (rect.isRounded())
        fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRight(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color);
    else
        fillRect(rect.rect(), color);
}

void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedRect& roundedHoleRect, const Color& color)
{
    if (contextDisabled())
        return;

    Path path;
    path.addRect(rect);

    if (!roundedHoleRect.radii().isZero())
        path.addRoundedRect(roundedHoleRect);
    else
        path.addRect(roundedHoleRect.rect());

    WindRule oldFillRule = fillRule();
    Color oldFillColor = fillColor();

    setFillRule(RULE_EVENODD);
    setFillColor(color);

    fillPath(path);

    setFillRule(oldFillRule);
    setFillColor(oldFillColor);
}

void GraphicsContext::clearRect(const FloatRect& rect)
{
    if (contextDisabled())
        return;

    SkRect r = rect;
    SkPaint paint(immutableState()->fillPaint());
    paint.setXfermodeMode(SkXfermode::kClear_Mode);
    drawRect(r, paint);
}

void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle penStyle)
{
    // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
    // works out.  For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g.,
    // (50+53)/2 = 103/2 = 51 when we want 51.5.  It is always true that an even width gave
    // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
    if (penStyle == DottedStroke || penStyle == DashedStroke) {
        if (p1.x() == p2.x()) {
            p1.setY(p1.y() + strokeWidth);
            p2.setY(p2.y() - strokeWidth);
        } else {
            p1.setX(p1.x() + strokeWidth);
            p2.setX(p2.x() - strokeWidth);
        }
    }

    if (static_cast<int>(strokeWidth) % 2) { //odd
        if (p1.x() == p2.x()) {
            // We're a vertical line.  Adjust our x.
            p1.setX(p1.x() + 0.5f);
            p2.setX(p2.x() + 0.5f);
        } else {
            // We're a horizontal line. Adjust our y.
            p1.setY(p1.y() + 0.5f);
            p2.setY(p2.y() + 0.5f);
        }
    }
}

PassOwnPtr<ImageBuffer> GraphicsContext::createRasterBuffer(const IntSize& size, OpacityMode opacityMode) const
{
    // Make the buffer larger if the context's transform is scaling it so we need a higher
    // resolution than one pixel per unit. Also set up a corresponding scale factor on the
    // graphics context.

    AffineTransform transform = getCTM();
    IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale())));

    SkAlphaType alphaType = (opacityMode == Opaque) ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
    SkImageInfo info = SkImageInfo::MakeN32(size.width(), size.height(), alphaType);
    RefPtr<SkSurface> skSurface = adoptRef(SkSurface::NewRaster(info));
    if (!skSurface)
        return nullptr;
    OwnPtr<ImageBufferSurface> surface = adoptPtr(new CompatibleImageBufferSurface(skSurface.release(), scaledSize, opacityMode));
    ASSERT(surface->isValid());
    OwnPtr<ImageBuffer> buffer = adoptPtr(new ImageBuffer(surface.release()));

    buffer->context()->scale(static_cast<float>(scaledSize.width()) / size.width(),
        static_cast<float>(scaledSize.height()) / size.height());

    return buffer.release();
}

void GraphicsContext::setPathFromConvexPoints(SkPath* path, size_t numPoints, const FloatPoint* points)
{
    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()));
    }

    /*  The code used to just blindly call this
            path->setIsConvex(true);
        But webkit can sometimes send us non-convex 4-point values, so we mark the path's
        convexity as unknown, so it will get computed by skia at draw time.
        See crbug.com 108605
    */
    SkPath::Convexity convexity = SkPath::kConvex_Convexity;
    if (numPoints == 4)
        convexity = SkPath::kUnknown_Convexity;
    path->setConvexity(convexity);
}

void GraphicsContext::setRadii(SkVector* radii, IntSize topLeft, IntSize topRight, IntSize bottomRight, IntSize bottomLeft)
{
    radii[SkRRect::kUpperLeft_Corner].set(SkIntToScalar(topLeft.width()),
        SkIntToScalar(topLeft.height()));
    radii[SkRRect::kUpperRight_Corner].set(SkIntToScalar(topRight.width()),
        SkIntToScalar(topRight.height()));
    radii[SkRRect::kLowerRight_Corner].set(SkIntToScalar(bottomRight.width()),
        SkIntToScalar(bottomRight.height()));
    radii[SkRRect::kLowerLeft_Corner].set(SkIntToScalar(bottomLeft.width()),
        SkIntToScalar(bottomLeft.height()));
}

PassRefPtr<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(ColorFilter colorFilter)
{
    switch (colorFilter) {
    case ColorFilterLuminanceToAlpha:
        return adoptRef(SkLumaColorFilter::Create());
    case ColorFilterLinearRGBToSRGB:
        return ImageBuffer::createColorSpaceFilter(ColorSpaceLinearRGB, ColorSpaceDeviceRGB);
    case ColorFilterSRGBToLinearRGB:
        return ImageBuffer::createColorSpaceFilter(ColorSpaceDeviceRGB, ColorSpaceLinearRGB);
    case ColorFilterNone:
        break;
    default:
        ASSERT_NOT_REACHED();
        break;
    }

    return nullptr;
}

#if !OS(MACOSX)
void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index)
{
    const SkPMColor lineColor = lineColors(index);
    const SkPMColor antiColor1 = antiColors1(index);
    const SkPMColor antiColor2 = antiColors2(index);

    uint32_t* row1 = bitmap->getAddr32(0, 0);
    uint32_t* row2 = bitmap->getAddr32(0, 1);
    uint32_t* row3 = bitmap->getAddr32(0, 2);
    uint32_t* row4 = bitmap->getAddr32(0, 3);

    // Pattern: X0o   o0X0o   o0
    //          XX0o o0XXX0o o0X
    //           o0XXX0o o0XXX0o
    //            o0X0o   o0X0o
    const SkPMColor row1Color[] = { lineColor, antiColor1, antiColor2, 0,          0,         0,          antiColor2, antiColor1 };
    const SkPMColor row2Color[] = { lineColor, lineColor,  antiColor1, antiColor2, 0,         antiColor2, antiColor1, lineColor };
    const SkPMColor row3Color[] = { 0,         antiColor2, antiColor1, lineColor,  lineColor, lineColor,  antiColor1, antiColor2 };
    const SkPMColor row4Color[] = { 0,         0,          antiColor2, antiColor1, lineColor, antiColor1, antiColor2, 0 };

    for (int x = 0; x < bitmap->width() + 8; x += 8) {
        int count = std::min(bitmap->width() - x, 8);
        if (count > 0) {
            memcpy(row1 + x, row1Color, count * sizeof(SkPMColor));
            memcpy(row2 + x, row2Color, count * sizeof(SkPMColor));
            memcpy(row3 + x, row3Color, count * sizeof(SkPMColor));
            memcpy(row4 + x, row4Color, count * sizeof(SkPMColor));
        }
    }
}

void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index)
{
    const uint32_t lineColor = lineColors(index);
    const uint32_t antiColor = antiColors2(index);

    // Pattern: X o   o X o   o X
    //            o X o   o X o
    uint32_t* row1 = bitmap->getAddr32(0, 0);
    uint32_t* row2 = bitmap->getAddr32(0, 1);
    for (int x = 0; x < bitmap->width(); x++) {
        switch (x % 4) {
        case 0:
            row1[x] = lineColor;
            break;
        case 1:
            row1[x] = antiColor;
            row2[x] = antiColor;
            break;
        case 2:
            row2[x] = lineColor;
            break;
        case 3:
            row1[x] = antiColor;
            row2[x] = antiColor;
            break;
        }
    }
}

SkPMColor GraphicsContext::lineColors(int index)
{
    static const SkPMColor colors[] = {
        SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red.
        SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0) // Opaque gray.
    };

    return colors[index];
}

SkPMColor GraphicsContext::antiColors1(int index)
{
    static const SkPMColor colors[] = {
        SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red.
        SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0)  // Semitransparent gray.
    };

    return colors[index];
}

SkPMColor GraphicsContext::antiColors2(int index)
{
    static const SkPMColor colors[] = {
        SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red
        SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0)  // More transparent gray
    };

    return colors[index];
}
#endif

void GraphicsContext::didDrawTextInRect(const SkRect& textRect)
{
    if (m_trackTextRegion) {
        TRACE_EVENT0("skia", "GraphicsContext::didDrawTextInRect");
        m_textRegion.join(textRect);
    }
}

void GraphicsContext::preparePaintForDrawRectToRect(
    SkPaint* paint,
    const SkRect& srcRect,
    const SkRect& destRect,
    CompositeOperator compositeOp,
    WebBlendMode blendMode,
    bool isLazyDecoded,
    bool isDataComplete) const
{
    paint->setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp, blendMode));
    paint->setColorFilter(this->colorFilter());
    paint->setAlpha(this->getNormalizedAlpha());
    paint->setLooper(this->drawLooper());
    paint->setAntiAlias(shouldDrawAntiAliased(this, destRect));

    InterpolationQuality resampling;
    if (this->isAccelerated()) {
        resampling = InterpolationLow;
    } else if (isLazyDecoded) {
        resampling = InterpolationHigh;
    } else {
        // Take into account scale applied to the canvas when computing sampling mode (e.g. CSS scale or page scale).
        SkRect destRectTarget = destRect;
        SkMatrix totalMatrix = this->getTotalMatrix();
        if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
            totalMatrix.mapRect(&destRectTarget, destRect);

        resampling = computeInterpolationQuality(totalMatrix,
            SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()),
            SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height()),
            isDataComplete);
    }

    if (resampling == InterpolationNone) {
        // FIXME: This is to not break tests (it results in the filter bitmap flag
        // being set to true). We need to decide if we respect InterpolationNone
        // being returned from computeInterpolationQuality.
        resampling = InterpolationLow;
    }
    resampling = limitInterpolationQuality(this, resampling);
    paint->setFilterLevel(static_cast<SkPaint::FilterLevel>(resampling));
}

} // namespace blink
