diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index def50823b82..c1e92798c96 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -65,8 +65,9 @@ SkColor ColorToSkColor(const Color &color, Float aAlpha) class GradientStopsSkia : public GradientStops { public: - GradientStopsSkia(const std::vector& aStops, uint32_t aNumStops) + GradientStopsSkia(const std::vector& aStops, uint32_t aNumStops, ExtendMode aExtendMode) : mCount(aNumStops) + , mExtendMode(aExtendMode) { if (mCount == 0) { return; @@ -103,6 +104,7 @@ public: std::vector mColors; std::vector mPositions; int mCount; + ExtendMode mExtendMode; }; SkXfermode::Mode @@ -208,12 +210,89 @@ ExtendModeToTileMode(ExtendMode aMode) return SkShader::kClamp_TileMode; } +void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, Float aAlpha = 1.0) +{ + switch (aPattern.GetType()) { + case PATTERN_COLOR: { + Color color = static_cast(aPattern).mColor; + aPaint.setColor(ColorToSkColor(color, aAlpha)); + break; + } + case PATTERN_LINEAR_GRADIENT: { + const LinearGradientPattern& pat = static_cast(aPattern); + GradientStopsSkia *stops = static_cast(pat.mStops.get()); + SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); + + if (stops->mCount >= 2) { + SkPoint points[2]; + points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y)); + points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y)); + + SkShader* shader = SkGradientShader::CreateLinear(points, + &stops->mColors.front(), + &stops->mPositions.front(), + stops->mCount, + mode); + SkMatrix mat; + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); + shader->setLocalMatrix(mat); + SkSafeUnref(aPaint.setShader(shader)); + } else { + aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); + } + break; + } + case PATTERN_RADIAL_GRADIENT: { + const RadialGradientPattern& pat = static_cast(aPattern); + GradientStopsSkia *stops = static_cast(pat.mStops.get()); + SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); + + if (stops->mCount >= 2) { + SkPoint points[2]; + points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y)); + points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y)); + + SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0], + SkFloatToScalar(pat.mRadius1), + points[1], + SkFloatToScalar(pat.mRadius2), + &stops->mColors.front(), + &stops->mPositions.front(), + stops->mCount, + mode); + SkMatrix mat; + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); + shader->setLocalMatrix(mat); + SkSafeUnref(aPaint.setShader(shader)); + } else { + aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); + } + break; + } + case PATTERN_SURFACE: { + const SurfacePattern& pat = static_cast(aPattern); + const SkBitmap& bitmap = static_cast(pat.mSurface.get())->GetBitmap(); + + SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode); + SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode); + SkMatrix mat; + GfxMatrixToSkiaMatrix(pat.mMatrix, mat); + shader->setLocalMatrix(mat); + SkSafeUnref(aPaint.setShader(shader)); + if (pat.mFilter == FILTER_POINT) { + aPaint.setFilterBitmap(false); + } + break; + } + } +} + struct AutoPaintSetup { AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions, const Pattern& aPattern) : mNeedsRestore(false), mAlpha(1.0) { Init(aCanvas, aOptions); - SetPattern(aPattern); + SetPaintPattern(mPaint, aPattern, mAlpha); } AutoPaintSetup(SkCanvas *aCanvas, const DrawOptions& aOptions) @@ -261,60 +340,6 @@ struct AutoPaintSetup { mPaint.setFilterBitmap(true); } - void SetPattern(const Pattern& aPattern) - { - if (aPattern.GetType() == PATTERN_COLOR) { - Color color = static_cast(aPattern).mColor; - mPaint.setColor(ColorToSkColor(color, mAlpha)); - } else if (aPattern.GetType() == PATTERN_LINEAR_GRADIENT) { - const LinearGradientPattern& pat = static_cast(aPattern); - GradientStopsSkia *stops = static_cast(pat.mStops.get()); - - if (stops->mCount >= 2) { - SkPoint points[2]; - points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y)); - points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y)); - - SkShader* shader = SkGradientShader::CreateLinear(points, - &stops->mColors.front(), - &stops->mPositions.front(), - stops->mCount, - SkShader::kClamp_TileMode); - SkSafeUnref(mPaint.setShader(shader)); - } else { - mPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); - } - } else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) { - const RadialGradientPattern& pat = static_cast(aPattern); - GradientStopsSkia *stops = static_cast(pat.mStops.get()); - - if (stops->mCount >= 2) { - SkPoint points[2]; - points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y)); - points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y)); - - SkShader* shader = SkGradientShader::CreateTwoPointRadial(points[0], - SkFloatToScalar(pat.mRadius1), - points[1], - SkFloatToScalar(pat.mRadius2), - &stops->mColors.front(), - &stops->mPositions.front(), - stops->mCount, - SkShader::kClamp_TileMode); - SkSafeUnref(mPaint.setShader(shader)); - } else { - mPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); - } - } else { - const SurfacePattern& pat = static_cast(aPattern); - const SkBitmap& bitmap = static_cast(pat.mSurface.get())->GetBitmap(); - - SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode); - SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode); - SkSafeUnref(mPaint.setShader(shader)); - } - } - // TODO: Maybe add an operator overload to access this easier? SkPaint mPaint; bool mNeedsRestore; @@ -542,6 +567,36 @@ DrawTargetSkia::FillGlyphs(ScaledFont *aFont, mCanvas->drawPosText(&indices.front(), aBuffer.mNumGlyphs*2, &offsets.front(), paint.mPaint); } +void +DrawTargetSkia::Mask(const Pattern &aSource, + const Pattern &aMask, + const DrawOptions &aOptions) +{ + MarkChanged(); + AutoPaintSetup paint(mCanvas.get(), aOptions, aSource); + + SkPaint maskPaint; + SetPaintPattern(maskPaint, aMask); + + SkLayerRasterizer *raster = new SkLayerRasterizer(); + raster->addLayer(maskPaint); + SkSafeUnref(paint.mPaint.setRasterizer(raster)); + + // Skia only uses the mask rasterizer when we are drawing a path/rect. + // Take our destination bounds and convert them into user space to use + // as the path to draw. + SkPath path; + path.addRect(SkRect::MakeWH(mSize.width, mSize.height)); + + Matrix temp = mTransform; + temp.Invert(); + SkMatrix mat; + GfxMatrixToSkiaMatrix(temp, mat); + path.transform(mat); + + mCanvas->drawPath(path, paint.mPaint); +} + TemporaryRef DrawTargetSkia::CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, @@ -624,6 +679,21 @@ DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat) return true; } +void +DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) +{ + mBitmap.setConfig(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height, aStride); + mBitmap.setPixels(aData); + + SkAutoTUnref device(new SkDevice(mBitmap)); + SkAutoTUnref canvas(new SkCanvas(device.get())); + mSize = aSize; + + mDevice = device.get(); + mCanvas = canvas.get(); + mFormat = aFormat; +} + void DrawTargetSkia::SetTransform(const Matrix& aTransform) { @@ -665,6 +735,15 @@ DrawTargetSkia::PushClip(const Path *aPath) mCanvas->clipPath(skiaPath->GetPath()); } +void +DrawTargetSkia::PushClipRect(const Rect& aRect) +{ + SkRect rect = RectToSkRect(aRect); + + mCanvas->save(SkCanvas::kClip_SaveFlag); + mCanvas->clipRect(rect); +} + void DrawTargetSkia::PopClip() { @@ -681,7 +760,7 @@ DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, Ex } std::stable_sort(stops.begin(), stops.end()); - return new GradientStopsSkia(stops, aNumStops); + return new GradientStopsSkia(stops, aNumStops, aExtendMode); } void diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 650eae8d412..5f6637b0a97 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -101,10 +101,9 @@ public: const DrawOptions &aOptions = DrawOptions()); virtual void Mask(const Pattern &aSource, const Pattern &aMask, - const DrawOptions &aOptions = DrawOptions()) - { return; } + const DrawOptions &aOptions = DrawOptions()); virtual void PushClip(const Path *aPath); - virtual void PushClipRect(const Rect &aRect) { } + virtual void PushClipRect(const Rect& aRect); virtual void PopClip(); virtual TemporaryRef CreateSourceSurfaceFromData(unsigned char *aData, const IntSize &aSize, @@ -120,6 +119,7 @@ public: virtual void SetTransform(const Matrix &aTransform); bool Init(const IntSize &aSize, SurfaceFormat aFormat); + void Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat); operator std::string() const { std::stringstream stream; @@ -138,7 +138,6 @@ private: SkRefPtr mCanvas; SkRefPtr mDevice; nsRefPtr mImageSurface; - SurfaceFormat mFormat; vector mSnapshots; };