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