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