164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard/*
264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * Copyright 2006, The Android Open Source Project
364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *
464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * Redistribution and use in source and binary forms, with or without
564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * modification, are permitted provided that the following conditions
664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * are met:
764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *  * Redistributions of source code must retain the above copyright
864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *    notice, this list of conditions and the following disclaimer.
964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *  * Redistributions in binary form must reproduce the above copyright
1064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *    notice, this list of conditions and the following disclaimer in the
1164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *    documentation and/or other materials provided with the distribution.
1264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard *
1364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
1464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
1764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard */
2564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
2664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define LOG_TAG "PlatformGraphicsContext"
2764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#define LOG_NDEBUG 1
2864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
2964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "config.h"
3064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "PlatformGraphicsContext.h"
3164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
3264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "AndroidLog.h"
3364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkBlurDrawLooper.h"
3464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkBlurMaskFilter.h"
3564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkColorPriv.h"
3664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkDashPathEffect.h"
3764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkPaint.h"
3864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkShader.h"
3964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#include "SkiaUtils.h"
4064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
4164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardnamespace WebCore {
4264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
4364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
4464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Helper functions
4564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
4664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
4764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardstatic int RoundToInt(float x)
4864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
4964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return (int)roundf(x);
5064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
5164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
5264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardtemplate <typename T> T* deepCopyPtr(const T* src)
5364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
5464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return src ? new T(*src) : 0;
5564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
5664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
5764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Set a bitmap shader that mimics dashing by width-on, width-off.
5864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Returns false if it could not succeed (e.g. there was an existing shader)
5964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardstatic bool setBitmapDash(SkPaint* paint, int width) {
6064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (width <= 0 || paint->getShader())
6164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return false;
6264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
6364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkColor c = paint->getColor();
6464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
6564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkBitmap bm;
6664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
6764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    bm.allocPixels();
6864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    bm.lockPixels();
6964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
7064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // set the ON pixel
7164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
7264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                            SkColorGetG(c), SkColorGetB(c));
7364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // set the OFF pixel
7464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    *bm.getAddr32(1, 0) = 0;
7564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    bm.unlockPixels();
7664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
7764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkMatrix matrix;
7864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    matrix.setScale(SkIntToScalar(width), SK_Scalar1);
7964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
8064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
8164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                               SkShader::kClamp_TileMode);
8264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    s->setLocalMatrix(matrix);
8364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
8464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setShader(s)->unref();
85895fe04c32042264ad684bd498a0cd4729aae016Derek Sollenberger    paint->setFilterBitmap(true);
86895fe04c32042264ad684bd498a0cd4729aae016Derek Sollenberger    paint->setAntiAlias(true);
8764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return true;
8864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
8964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
9064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
9164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// State implementation
9264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
9364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
9464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::State::State()
9564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    : pathEffect(0)
9664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , miterLimit(4)
9764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , alpha(1)
9864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeThickness(0) // Same as default in GraphicsContextPrivate.h
9964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , lineCap(SkPaint::kDefault_Cap)
10064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , lineJoin(SkPaint::kDefault_Join)
10164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , mode(SkXfermode::kSrcOver_Mode)
10264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , dashRatio(3)
10364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , fillColor(SK_ColorBLACK)
10464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , fillShader(0)
10564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeColor(SK_ColorBLACK)
10664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeShader(0)
10764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , useAA(true)
10864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeStyle(SolidStroke)
10964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
11064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
11164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
11264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::State::State(const State& other)
11364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    : pathEffect(other.pathEffect)
11464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , miterLimit(other.miterLimit)
11564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , alpha(other.alpha)
11664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeThickness(other.strokeThickness)
11764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , lineCap(other.lineCap)
11864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , lineJoin(other.lineJoin)
11964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , mode(other.mode)
12064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , dashRatio(other.dashRatio)
12164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , shadow(other.shadow)
12264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , fillColor(other.fillColor)
12364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , fillShader(other.fillShader)
12464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeColor(other.strokeColor)
12564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeShader(other.strokeShader)
12664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , useAA(other.useAA)
12764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    , strokeStyle(other.strokeStyle)
12864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
12964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeRef(pathEffect);
13064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeRef(fillShader);
13164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeRef(strokeShader);
13264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
13364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
13464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::State::~State()
13564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
13664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeUnref(pathEffect);
13764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeUnref(fillShader);
13864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeUnref(strokeShader);
13964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
14064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
14164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::State::setShadow(int radius, int dx, int dy, SkColor c)
14264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
14364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Cut the radius in half, to visually match the effect seen in
14464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // safari browser
14564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    shadow.blur = SkScalarHalf(SkIntToScalar(radius));
14664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    shadow.dx = SkIntToScalar(dx);
14764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    shadow.dy = SkIntToScalar(dy);
14864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    shadow.color = c;
14964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
15064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
15164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardbool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* offset,
15264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                      bool shadowsIgnoreTransforms)
15364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
15464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setAntiAlias(true);
15564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setDither(true);
15664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setXfermodeMode(mode);
15764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setColor(shadow.color);
15864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    offset->set(shadow.dx, shadow.dy);
15964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
16064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // Currently, only GraphicsContexts associated with the
16164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // HTMLCanvasElement have shadows ignore transforms set.  This
16264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // allows us to distinguish between CSS and Canvas shadows which
16364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // have different rendering specifications.
164fca8b82bf07877fea8c7bef46a4b3f0b58db7a36John Reck    uint32_t flags = SkBlurMaskFilter::kNone_BlurFlag;
16564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (shadowsIgnoreTransforms) {
16664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        offset->fY = -offset->fY;
16764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
16864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
16964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
17064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (shadow.blur > 0) {
17164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
172fca8b82bf07877fea8c7bef46a4b3f0b58db7a36John Reck                             SkBlurMaskFilter::kNormal_BlurStyle, flags))->unref();
17364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
17464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
17564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
17664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
17764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardSkColor PlatformGraphicsContext::State::applyAlpha(SkColor c) const
17864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
17964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    int s = RoundToInt(alpha * 256);
18064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (s >= 256)
18164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return c;
18264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (s < 0)
18364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return 0;
18464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
18564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    int a = SkAlphaMul(SkColorGetA(c), s);
18664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return (c & 0x00FFFFFF) | (a << 24);
18764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
18864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
18964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Returns a new State with all of this object's inherited properties copied.
19064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties()
19164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
19264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return PlatformGraphicsContext::State(*this);
19364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
19464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
19564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
19664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// PlatformGraphicsContext
19764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
19864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
19964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::PlatformGraphicsContext()
20064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
20164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_stateStack.append(State());
20264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state = &m_stateStack.last();
20364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
20464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
20564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas RoardPlatformGraphicsContext::~PlatformGraphicsContext()
20664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
20764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
20864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
20964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
21064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// State management
21164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
21264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
21364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::save()
21464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
21564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_stateStack.append(m_state->cloneInheritedProperties());
21664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state = &m_stateStack.last();
21764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
21864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
21964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::restore()
22064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
22164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_stateStack.removeLast();
22264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state = &m_stateStack.last();
22364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
22464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
22564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
22664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// State setters
22764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
22864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
22964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setAlpha(float alpha)
23064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
23164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->alpha = alpha;
23264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
23364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
234d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reckint PlatformGraphicsContext::getNormalizedAlpha() const
235d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck{
236d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    int alpha = roundf(m_state->alpha * 256);
237d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    if (alpha > 255)
238d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck        alpha = 255;
239d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    else if (alpha < 0)
240d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck        alpha = 0;
241d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck    return alpha;
242d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck}
243d3bac753aa885a5dd91c4e608cc6c770d3d80dafJohn Reck
24464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setCompositeOperation(CompositeOperator op)
24564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
24664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->mode = WebCoreCompositeToSkiaComposite(op);
24764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
24864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
24953f84f58d9ffe86a4932c979b9863acadb5769efJohn Reckbool PlatformGraphicsContext::setFillColor(const Color& c)
25064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
25153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    bool dirty = false;
25253f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    if (m_state->fillColor != c.rgb()) {
25353f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        m_state->fillColor = c.rgb();
25453f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
25553f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    }
25653f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    return setFillShader(0) || dirty;
25764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
25864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
25953f84f58d9ffe86a4932c979b9863acadb5769efJohn Reckbool PlatformGraphicsContext::setFillShader(SkShader* fillShader)
26064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
26153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    bool dirty = false;
26253f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    if (fillShader && m_state->fillColor != Color::black) {
26364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->fillColor = Color::black;
26453f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
26553f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    }
26664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
26764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (fillShader != m_state->fillShader) {
26864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkSafeUnref(m_state->fillShader);
26964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->fillShader = fillShader;
27064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkSafeRef(m_state->fillShader);
27153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
27264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
27353f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    return dirty;
27464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
27564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
27664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setLineCap(LineCap cap)
27764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
27864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    switch (cap) {
27964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case ButtCap:
28064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineCap = SkPaint::kButt_Cap;
28164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
28264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case RoundCap:
28364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineCap = SkPaint::kRound_Cap;
28464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
28564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case SquareCap:
28664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineCap = SkPaint::kSquare_Cap;
28764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
28864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    default:
28964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        ALOGD("PlatformGraphicsContextSkia::setLineCap: unknown LineCap %d\n", cap);
29064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
29164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
29264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
29364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
29464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
29564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
29664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    size_t dashLength = dashes.size();
29764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!dashLength)
29864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return;
29964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
30064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
30164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkScalar* intervals = new SkScalar[count];
30264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
30364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    for (unsigned int i = 0; i < count; i++)
30464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
30564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPathEffect **effectPtr = &m_state->pathEffect;
30664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkSafeUnref(*effectPtr);
30764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
30864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
30964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    delete[] intervals;
31064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
31164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
31264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setLineJoin(LineJoin join)
31364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
31464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    switch (join) {
31564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case MiterJoin:
31664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineJoin = SkPaint::kMiter_Join;
31764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
31864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case RoundJoin:
31964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineJoin = SkPaint::kRound_Join;
32064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
32164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case BevelJoin:
32264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->lineJoin = SkPaint::kBevel_Join;
32364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
32464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    default:
32564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        ALOGD("PlatformGraphicsContextSkia::setLineJoin: unknown LineJoin %d\n", join);
32664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
32764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
32864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
32964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
33064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setMiterLimit(float limit)
33164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
33264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->miterLimit = limit;
33364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
33464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
33564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c)
33664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
33764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->setShadow(radius, dx, dy, c);
33864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
33964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
34064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setShouldAntialias(bool useAA)
34164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
34264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->useAA = useAA;
34364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
34464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
34553f84f58d9ffe86a4932c979b9863acadb5769efJohn Reckbool PlatformGraphicsContext::setStrokeColor(const Color& c)
34664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
34753f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    bool dirty = false;
34853f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    if (m_state->strokeColor != c.rgb()) {
34953f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        m_state->strokeColor = c.rgb();
35053f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
35153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    }
35253f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    return setStrokeShader(0) || dirty;
35364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
35464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
35553f84f58d9ffe86a4932c979b9863acadb5769efJohn Reckbool PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
35664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
35753f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    bool dirty = false;
35853f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    if (strokeShader && m_state->strokeColor != Color::black) {
35964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->strokeColor = Color::black;
36053f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
36153f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    }
36264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
36364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (strokeShader != m_state->strokeShader) {
36464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkSafeUnref(m_state->strokeShader);
36564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        m_state->strokeShader = strokeShader;
36664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkSafeRef(m_state->strokeShader);
36753f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck        dirty = true;
36864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
36953f84f58d9ffe86a4932c979b9863acadb5769efJohn Reck    return dirty;
37064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
37164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
37264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setStrokeStyle(StrokeStyle style)
37364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
37464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->strokeStyle = style;
37564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
37664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
37764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setStrokeThickness(float f)
37864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
37964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    m_state->strokeThickness = f;
38064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
38164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
38264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
38364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard// Paint setup
38464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard//**************************************
38564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
38664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const
38764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
38864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setAntiAlias(m_state->useAA);
38964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setDither(true);
39064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setXfermodeMode(m_state->mode);
39164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (SkColorGetA(m_state->shadow.color) > 0) {
39264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
39364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Currently, only GraphicsContexts associated with the
39464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // HTMLCanvasElement have shadows ignore transforms set.  This
39564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // allows us to distinguish between CSS and Canvas shadows which
39664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // have different rendering specifications.
39764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkScalar dy = m_state->shadow.dy;
398fca8b82bf07877fea8c7bef46a4b3f0b58db7a36John Reck        uint32_t flags = SkBlurDrawLooper::kNone_BlurFlag;
39964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        if (shadowsIgnoreTransforms()) {
40064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            dy = -dy;
40164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
40264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag;
40364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        }
40464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
40564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
40664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    m_state->shadow.dx,
40764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    dy,
40864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    m_state->shadow.color,
40964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                                    flags);
41064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint->setLooper(looper)->unref();
41164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
41264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setFilterBitmap(true);
41364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
41464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
41564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardvoid PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const
41664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
41764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    this->setupPaintCommon(paint);
41864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setColor(m_state->applyAlpha(m_state->fillColor));
41964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setShader(m_state->fillShader);
42064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
42164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
42264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardbool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const
42364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
42464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms());
42564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
42664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
42764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roardbool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect,
42864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard                                               bool isHLine)
42964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard{
43064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    this->setupPaintCommon(paint);
43164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setColor(m_state->applyAlpha(m_state->strokeColor));
43264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setShader(m_state->strokeShader);
43364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
43464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    float width = m_state->strokeThickness;
43564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
43664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // This allows dashing and dotting to work properly for hairline strokes
43764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    // FIXME: Should we only do this for dashed and dotted strokes?
43864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (!width)
43964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        width = 1;
44064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
44164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setStyle(SkPaint::kStroke_Style);
44264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setStrokeWidth(SkFloatToScalar(width));
44364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setStrokeCap(m_state->lineCap);
44464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setStrokeJoin(m_state->lineJoin);
44564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit));
44664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
44764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (rect && (RoundToInt(width) & 1))
44864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
44964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
45064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    SkPathEffect* pe = m_state->pathEffect;
45164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (pe) {
45264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        paint->setPathEffect(pe);
45364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return false;
45464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
45564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    switch (m_state->strokeStyle) {
45664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case NoStroke:
45764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case SolidStroke:
45864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        width = 0;
45964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
46064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case DashedStroke:
46164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        width = m_state->dashRatio * width;
46264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
46364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // No break
46464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    case DottedStroke:
46564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        break;
46664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
46764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
46864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    if (width > 0) {
46964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        // Return true if we're basically a dotted dash of squares
47064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth());
47164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
47264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        if (justSqrs || !isHLine || !setBitmapDash(paint, width)) {
47364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#if 0
47464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            // this is slow enough that we just skip it for now
47564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            // see http://b/issue?id=4163023
47664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            SkScalar intervals[] = { width, width };
47764e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            pe = new SkDashPathEffect(intervals, 2, 0);
47864e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard            paint->setPathEffect(pe)->unref();
47964e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard#endif
48064e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        }
48164e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard        return justSqrs;
48264e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    }
48364e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard    return false;
48464e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}
48564e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard
48664e4b265f84573b97d408f7d3e5aa99a647be057Nicolas Roard}   // WebCore
487