164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define LOG_TAG "PlatformGraphicsContextSkia"
264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define LOG_NDEBUG 1
364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "config.h"
564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "PlatformGraphicsContextSkia.h"
664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "AndroidLog.h"
864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "Font.h"
964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "GraphicsContext.h"
1064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkCanvas.h"
1164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkCornerPathEffect.h"
1264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkPaint.h"
1364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkShader.h"
1464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkiaUtils.h"
1564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
1664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardnamespace WebCore {
1764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
1864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// These are the flags we need when we call saveLayer for transparency.
1964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Since it does not appear that webkit intends this to also save/restore
2064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// the matrix or clip, I do not give those flags (for performance)
2164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define TRANSPARENCY_SAVEFLAGS                                  \
2264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag |   \
2364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                          SkCanvas::kFullColorLayer_SaveFlag)
2464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
2564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
2664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Helper functions
2764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
2864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
2964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardstatic void setrectForUnderline(SkRect* r, float lineThickness,
3064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                const FloatPoint& point, int yOffset, float width)
3164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
3264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#if 0
3364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (lineThickness < 1) // Do we really need/want this?
3464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        lineThickness = 1;
3564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#endif
3664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    r->fLeft    = point.x();
3764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    r->fTop     = point.y() + yOffset;
3864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    r->fRight   = r->fLeft + width;
3964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    r->fBottom  = r->fTop + lineThickness;
4064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
4164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
4264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardstatic inline int fastMod(int value, int max)
4364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
4464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    int sign = SkExtractSign(value);
4564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
4664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    value = SkApplySign(value, sign);
4764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (value >= max)
4864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        value %= max;
4964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return SkApplySign(value, sign);
5064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
5164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
5264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardstatic inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
5364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    /*  Bitmaps may be drawn to seem next to other images. If we are drawn
5464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        zoomed, or at fractional coordinates, we may see cracks/edges if
5564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        we antialias, because that will cause us to draw the same pixels
5664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        more than once (e.g. from the left and right bitmaps that share
5764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        an edge).
5864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
5964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        Disabling antialiasing fixes this, and since so far we are never
6064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        rotated at non-multiple-of-90 angles, this seems to do no harm
6164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard     */
6264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setAntiAlias(false);
6364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
6464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
6564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
6664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// PlatformGraphicsContextSkia
6764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
6864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
6964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContextSkia::PlatformGraphicsContextSkia(SkCanvas* canvas,
7064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                         bool takeCanvasOwnership)
7164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    : PlatformGraphicsContext()
7264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , mCanvas(canvas)
7364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , m_deleteCanvas(takeCanvasOwnership)
7464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
7564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_gc = 0;
7664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
7764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
7864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContextSkia::~PlatformGraphicsContextSkia()
7964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
8064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_deleteCanvas)
8164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        delete mCanvas;
8264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
8364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
8464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardbool PlatformGraphicsContextSkia::isPaintingDisabled()
8564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
8664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return !mCanvas;
8764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
8864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
8964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
9064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// State management
9164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
9264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
9364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::beginTransparencyLayer(float opacity)
9464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
9564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkCanvas* canvas = mCanvas;
9664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
9764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
9864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
9964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::endTransparencyLayer()
10064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
10164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!mCanvas)
10264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
10364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->restore();
10464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
10564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
10664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::save()
10764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
10864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    PlatformGraphicsContext::save();
10964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Save our native canvas.
11064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->save();
11164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
11264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
11364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::restore()
11464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
11564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    PlatformGraphicsContext::restore();
11664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Restore our native canvas.
11764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->restore();
11864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
11964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
12064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
12164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Matrix operations
12264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
12364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
12464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::concatCTM(const AffineTransform& affine)
12564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
12664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->concat(affine);
12764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
12864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
12964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::rotate(float angleInRadians)
13064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
13164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    float value = angleInRadians * (180.0f / 3.14159265f);
13264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->rotate(SkFloatToScalar(value));
13364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
13464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
13564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::scale(const FloatSize& size)
13664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
13764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
13864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
13964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
14064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::translate(float x, float y)
14164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
14264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y));
14364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
14464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
14564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardconst SkMatrix& PlatformGraphicsContextSkia::getTotalMatrix()
14664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
14764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return mCanvas->getTotalMatrix();
14864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
14964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
15064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
15164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Clipping
15264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
15364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
15464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::addInnerRoundedRectClip(const IntRect& rect,
15564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                      int thickness)
15664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
15764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path;
15864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect r(rect);
15964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
16064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.addOval(r, SkPath::kCW_Direction);
16164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Only perform the inset if we won't invert r
16264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
16364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Adding one to the thickness doesn't make the border too thick as
16464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // it's painted over afterwards. But without this adjustment the
16564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // border appears a little anemic after anti-aliasing.
16664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
16764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        path.addOval(r, SkPath::kCCW_Direction);
16864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
16964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipPath(path, SkRegion::kIntersect_Op, true);
17064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
17164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
17264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::canvasClip(const Path& path)
17364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
17464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    clip(path);
17564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
17664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
17764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clip(const FloatRect& rect)
17864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
17964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipRect(rect);
18064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
18164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
18264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clip(const Path& path)
18364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
18464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
18564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
18664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
18764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints,
18864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                const FloatPoint*, bool antialias)
18964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
19064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (numPoints <= 1)
19164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
19264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
19364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined
19464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // in RenderObject.h which it isn't for us. TODO: Support that :)
19564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
19664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
19764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clipOut(const IntRect& r)
19864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
19964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipRect(r, SkRegion::kDifference_Op);
20064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
20164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
20264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clipOut(const Path& path)
20364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
20464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op);
20564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
20664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
20764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule)
20864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
20964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path = *pathToClip.platformPath();
21064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.setFillType(clipRule == RULE_EVENODD
21164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
21264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->clipPath(path);
21364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
21464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::clearRect(const FloatRect& rect)
21564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
21664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
21764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
21864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintFill(&paint);
21964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setXfermodeMode(SkXfermode::kClear_Mode);
22064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
22164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(rect, paint);
22264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
22364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
22464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
22564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Drawing
22664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
22764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
22864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawBitmapPattern(
22964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const SkBitmap& bitmap, const SkMatrix& matrix,
23064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        CompositeOperator compositeOp, const FloatRect& destRect)
23164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
23264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkShader* shader = SkShader::CreateBitmapShader(bitmap,
23364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    SkShader::kRepeat_TileMode,
23464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    SkShader::kRepeat_TileMode);
23564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    shader->setLocalMatrix(matrix);
23664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
237d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    setupPaintCommon(&paint);
238d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    paint.setAlpha(getNormalizedAlpha());
23964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setShader(shader);
24064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
24164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    fixPaintForBitmapsThatMaySeam(&paint);
24264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(destRect, paint);
24364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
24464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
24564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawBitmapRect(const SkBitmap& bitmap,
24664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                             const SkIRect* src, const SkRect& dst,
24764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                             CompositeOperator op)
24864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
24964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
250d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    setupPaintCommon(&paint);
251d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    paint.setAlpha(getNormalizedAlpha());
25264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op));
25364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    fixPaintForBitmapsThatMaySeam(&paint);
25464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
25564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawBitmapRect(bitmap, src, dst, &paint);
25664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
25764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
25864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints,
25964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                const FloatPoint* points,
26064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                bool shouldAntialias)
26164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
26264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (numPoints <= 1)
26364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
26464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
26564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
26664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path;
26764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
26864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.incReserve(numPoints);
26964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
27064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    for (size_t i = 1; i < numPoints; i++)
27164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));
27264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
27364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (mCanvas->quickReject(path, shouldAntialias ?
27464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
27564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
27664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
27764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
27864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->fillColor & 0xFF000000) {
27964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintFill(&paint);
28064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setAntiAlias(shouldAntialias);
28164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawPath(path, paint);
28264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
28364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
28464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->strokeStyle != NoStroke) {
28564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.reset();
28664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintStroke(&paint, 0);
28764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setAntiAlias(shouldAntialias);
28864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawPath(path, paint);
28964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
29064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
29164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
29264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect)
29364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
29464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
29564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect oval(rect);
29664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
29764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->fillColor & 0xFF000000) {
29864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintFill(&paint);
29964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawOval(oval, paint);
30064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
30164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->strokeStyle != NoStroke) {
30264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.reset();
30364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintStroke(&paint, &oval);
30464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawOval(oval, paint);
30564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
30664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
30764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
30864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawFocusRing(const Vector<IntRect>& rects,
30964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                            int /* width */, int /* offset */,
31064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                            const Color& color)
31164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
31264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    unsigned rectCount = rects.size();
31364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!rectCount)
31464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
31564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
31664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRegion focusRingRegion;
31764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8);
31864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    for (unsigned i = 0; i < rectCount; i++) {
31964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkIRect r = rects[i];
32064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        r.inset(-focusRingOutset, -focusRingOutset);
32164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        focusRingRegion.op(r, SkRegion::kUnion_Op);
32264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
32364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
32464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path;
32564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
32664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setAntiAlias(true);
32764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setStyle(SkPaint::kStroke_Style);
32864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
32964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setColor(color.rgb());
33064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setStrokeWidth(focusRingOutset * 2);
33164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref();
33264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    focusRingRegion.getBoundaryPath(&path);
33364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawPath(path, paint);
33464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
33564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
33664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawHighlightForText(
33764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const Font& font, const TextRun& run, const FloatPoint& point, int h,
33864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const Color& backgroundColor, ColorSpace colorSpace, int from,
33964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        int to, bool isActive)
34064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
34164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
34264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (isActive)
34364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        fillRect(rect, backgroundColor);
34464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    else {
34564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
34664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const int t = 3, t2 = t * 2;
34764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
34864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        fillRect(IntRect(x, y, w, t), backgroundColor);
34964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        fillRect(IntRect(x, y+h-t, w, t), backgroundColor);
35064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        fillRect(IntRect(x, y+t, t, h-t2), backgroundColor);
35164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor);
35264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
35364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
35464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
35564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawLine(const IntPoint& point1,
35664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                       const IntPoint& point2)
35764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
35864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    StrokeStyle style = m_state->strokeStyle;
35964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (style == NoStroke)
36064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
36164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
36264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
36364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkCanvas* canvas = mCanvas;
36464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    const int idx = SkAbs32(point2.x() - point1.x());
36564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    const int idy = SkAbs32(point2.y() - point1.y());
36664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
36764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Special-case horizontal and vertical lines that are really just dots
36864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
36964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const SkScalar diameter = paint.getStrokeWidth();
37064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const SkScalar radius = SkScalarHalf(diameter);
37164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
37264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
37364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkScalar dx, dy;
37464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        int count;
37564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkRect bounds;
37664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
37764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        if (!idy) { // Horizontal
37864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
37964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            x += radius;
38064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            dx = diameter * 2;
38164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            dy = 0;
38264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            count = idx;
38364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        } else { // Vertical
38464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
38564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            y += radius;
38664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            dx = 0;
38764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            dy = diameter * 2;
38864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            count = idy;
38964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        }
39064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
39164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // The actual count is the number of ONs we hit alternating
39264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // ON(diameter), OFF(diameter), ...
39364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        {
39464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
39564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            // Now compute the number of cells (ON and OFF)
39664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            count = SkScalarRound(width);
39764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            // Now compute the number of ONs
39864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            count = (count + 1) >> 1;
39964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        }
40064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
40164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkAutoMalloc storage(count * sizeof(SkPoint));
40264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkPoint* verts = (SkPoint*)storage.get();
40364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Now build the array of vertices to past to drawPoints
40464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        for (int i = 0; i < count; i++) {
40564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            verts[i].set(x, y);
40664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            x += dx;
40764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            y += dy;
40864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        }
40964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
41064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setStyle(SkPaint::kFill_Style);
41164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setPathEffect(0);
41264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
41364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Clipping to bounds is not required for correctness, but it does
41464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // allow us to reject the entire array of points if we are completely
41564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // offscreen. This is common in a webpage for android, where most of
41664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // the content is clipped out. If drawPoints took an (optional) bounds
41764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // parameter, that might even be better, as we would *just* use it for
41864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // culling, and not both wacking the canvas' save/restore stack.
41964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        canvas->save(SkCanvas::kClip_SaveFlag);
42064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        canvas->clipRect(bounds);
42164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
42264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        canvas->restore();
42364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    } else {
42464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkPoint pts[2] = { point1, point2 };
42564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
42664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
42764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
42864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
42964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawLineForText(const FloatPoint& pt, float width)
43064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
43164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect r;
43264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
43364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
43464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
43564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setAntiAlias(true);
43664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setColor(m_state->strokeColor);
43764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
43864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(r, paint);
43964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
44064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
44164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawLineForTextChecking(const FloatPoint& pt,
44264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        float width, GraphicsContext::TextCheckingLineStyle)
44364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
44464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // TODO: Should we draw different based on TextCheckingLineStyle?
44564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect r;
44664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
44764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
44864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
44964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setAntiAlias(true);
45064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setColor(SK_ColorRED); // Is this specified somewhere?
45164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
45264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(r, paint);
45364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
45464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
45564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::drawRect(const IntRect& rect)
45664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
45764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
45864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect r(rect);
45964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
46064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->fillColor & 0xFF000000) {
46164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintFill(&paint);
46264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawRect(r, paint);
46364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
46464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
46564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // According to GraphicsContext.h, stroking inside drawRect always means
46664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // a stroke of 1 inside the rect.
46764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) {
46864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.reset();
46964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintStroke(&paint, &r);
47064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setPathEffect(0); // No dashing please
47164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
47264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
47364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawRect(r, paint);
47464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
47564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
47664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
47764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::fillPath(const Path& pathToFill, WindRule fillRule)
47864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
47964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath* path = pathToFill.platformPath();
48064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!path)
48164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
48264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
48364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    switch (fillRule) {
48464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case RULE_NONZERO:
48564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        path->setFillType(SkPath::kWinding_FillType);
48664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
48764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case RULE_EVENODD:
48864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        path->setFillType(SkPath::kEvenOdd_FillType);
48964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
49064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
49164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
49264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
49364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintFill(&paint);
49464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
49564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawPath(*path, paint);
49664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
49764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
49864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::fillRect(const FloatRect& rect)
49964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
50064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
50164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintFill(&paint);
50264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(rect, paint);
50364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
50464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
50564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::fillRect(const FloatRect& rect,
50664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                       const Color& color)
50764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
50864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (color.rgb() & 0xFF000000) {
50964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkPaint paint;
51064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
51164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintCommon(&paint);
51264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setColor(color.rgb()); // Punch in the specified color
51364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setShader(0); // In case we had one set
51464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
51564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Sometimes we record and draw portions of the page, using clips
51664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // for each portion. The problem with this is that webkit, sometimes,
51764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // sees that we're only recording a portion, and they adjust some of
51864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // their rectangle coordinates accordingly (e.g.
51964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // RenderBoxModelObject::paintFillLayerExtended() which calls
52064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // rect.intersect(paintInfo.rect) and then draws the bg with that
52164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // rect. The result is that we end up drawing rects that are meant to
52264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // seam together (one for each portion), but if the rects have
52364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // fractional coordinates (e.g. we are zoomed by a fractional amount)
52464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // we will double-draw those edges, resulting in visual cracks or
52564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // artifacts.
52664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
52764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // The fix seems to be to just turn off antialasing for rects (this
52864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // entry-point in GraphicsContext seems to have been sufficient,
52964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // though perhaps we'll find we need to do this as well in fillRect(r)
53064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // as well.) Currently setupPaintCommon() enables antialiasing.
53164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
53264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Since we never show the page rotated at a funny angle, disabling
53364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // antialiasing seems to have no real down-side, and it does fix the
53464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // bug when we're zoomed (and drawing portions that need to seam).
53564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setAntiAlias(false);
53664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
53764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        mCanvas->drawRect(rect, paint);
53864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
53964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
54064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
54164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::fillRoundedRect(
54264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
54364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const IntSize& bottomLeft, const IntSize& bottomRight,
54464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        const Color& color)
54564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
54664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
54764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path;
54864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkScalar radii[8];
54964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
55064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[0] = SkIntToScalar(topLeft.width());
55164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[1] = SkIntToScalar(topLeft.height());
55264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[2] = SkIntToScalar(topRight.width());
55364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[3] = SkIntToScalar(topRight.height());
55464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[4] = SkIntToScalar(bottomRight.width());
55564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[5] = SkIntToScalar(bottomRight.height());
55664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[6] = SkIntToScalar(bottomLeft.width());
55764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    radii[7] = SkIntToScalar(bottomLeft.height());
55864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.addRoundRect(rect, radii);
55964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
56064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintFill(&paint);
56164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setColor(color.rgb());
56264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawPath(path, paint);
56364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
56464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
56564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::strokeArc(const IntRect& r, int startAngle,
56664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                        int angleSpan)
56764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
56864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPath path;
56964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
57064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkRect oval(r);
57164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
57264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (m_state->strokeStyle == NoStroke) {
57364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintFill(&paint); // We want the fill color
57464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setStyle(SkPaint::kStroke_Style);
57564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness));
57664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    } else
57764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        setupPaintStroke(&paint, 0);
57864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
57964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // We do this before converting to scalar, so we don't overflow SkFixed
58064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    startAngle = fastMod(startAngle, 360);
58164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    angleSpan = fastMod(angleSpan, 360);
58264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
58364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
58464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawPath(path, paint);
58564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
58664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
58764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::strokePath(const Path& pathToStroke)
58864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
58964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    const SkPath* path = pathToStroke.platformPath();
59064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!path)
59164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
59264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
59364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
59464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintStroke(&paint, 0);
59564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
59664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawPath(*path, paint);
59764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
59864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
59964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContextSkia::strokeRect(const FloatRect& rect, float lineWidth)
60064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
60164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPaint paint;
60264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
60364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    setupPaintStroke(&paint, 0);
60464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint.setStrokeWidth(SkFloatToScalar(lineWidth));
60564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    mCanvas->drawRect(rect, paint);
60664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
60764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
60864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}   // WebCore
609