diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index eb255c7f214f..fae0bcf40cd1 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -287,8 +287,7 @@ public: mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight); - static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5; - int32_t blurRadius = (int32_t) floor(mSigma * GAUSSIAN_SCALE_FACTOR + 0.5); + Float blurRadius = mSigma * 3; // We need to enlarge and possibly offset our temporary surface // so that things outside of the canvas may cast shadows. @@ -306,21 +305,14 @@ public: mTempRect = mTempRect.Intersect(*aBounds); } - // Nothing to draw - if (mTempRect.IsEmpty()) { - mTarget = ctx->mTarget; - mCtx = nullptr; - return; - } - mTempRect.ScaleRoundOut(1.0f); transform._31 -= mTempRect.x; transform._32 -= mTempRect.y; mTarget = - mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), - FORMAT_B8G8R8A8, mSigma); + mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)), + FORMAT_B8G8R8A8); if (!mTarget) { // XXX - Deal with the situation where our temp size is too big to @@ -3110,9 +3102,8 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP buffer.mGlyphs = &glyphBuf.front(); buffer.mNumGlyphs = glyphBuf.size(); - Rect bounds(mBoundingBox.x, mBoundingBox.y, mBoundingBox.width, mBoundingBox.height); if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) { - AdjustedTarget(mCtx, &bounds)-> + AdjustedTarget(mCtx)-> FillGlyphs(scaledFont, buffer, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget), @@ -3121,7 +3112,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessorAzure : public nsBidiPresUtils::BidiP RefPtr path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget); const ContextState& state = *mState; - AdjustedTarget(mCtx, &bounds)-> + AdjustedTarget(mCtx)-> Stroke(path, CanvasGeneralPattern(). ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget), StrokeOptions(state.lineWidth, state.lineJoin, diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 2ace78465493..bc12195a6742 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -727,21 +727,6 @@ public: virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0; - /* - * Create a draw target optimized for drawing a shadow. - * - * Note that aSigma is the blur radius that must be used when we draw the - * shadow. Also note that this doesn't affect the size of the allocated - * surface, the caller is still responsible for including the shadow area in - * its size. - */ - virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const - { - return CreateSimilarDrawTarget(aSize, aFormat); - } - /* * Create a path builder with the specified fillmode. * diff --git a/gfx/2d/Blur.cpp b/gfx/2d/Blur.cpp index 6849d8b21769..9fe879836307 100644 --- a/gfx/2d/Blur.cpp +++ b/gfx/2d/Blur.cpp @@ -330,8 +330,7 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, const Rect* aSkipRect) : mSpreadRadius(aSpreadRadius), mBlurRadius(aBlurRadius), - mData(nullptr), - mFreeData(true) + mData(nullptr) { Rect rect(aRect); rect.Inflate(Size(aBlurRadius + aSpreadRadius)); @@ -385,25 +384,9 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect, } } -AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData, - const Rect& aRect, - int32_t aStride, - float aSigma) - : mSpreadRadius(), - mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))), - mData(aData), - mFreeData(false), - mStride(aStride), - mRect(aRect.x, aRect.y, aRect.width, aRect.height) -{ -} - - AlphaBoxBlur::~AlphaBoxBlur() { - if (mFreeData) { - delete mData; - } + free(mData); } unsigned char* diff --git a/gfx/2d/Blur.h b/gfx/2d/Blur.h index 68bb06d4a9f4..30d84e296de5 100644 --- a/gfx/2d/Blur.h +++ b/gfx/2d/Blur.h @@ -57,11 +57,6 @@ public: const Rect* aDirtyRect, const Rect* aSkipRect); - AlphaBoxBlur(uint8_t* aData, - const Rect& aRect, - int32_t aStride, - float aSigma); - ~AlphaBoxBlur(); /** @@ -140,12 +135,7 @@ private: /** * A pointer to the backing 8-bit alpha surface. */ - uint8_t* mData; - - /** - * True if we need to dispose the data. - */ - bool mFreeData; + unsigned char* mData; /** * The stride of the data contained in mData. diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index 97ca9e494779..10e305007f55 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -11,7 +11,6 @@ #include "ScaledFontBase.h" #include "cairo.h" -#include "cairo-tee.h" #include #include "Blur.h" @@ -388,35 +387,49 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, return; } + WillChange(); + Float width = aSurface->GetSize().width; Float height = aSurface->GetSize().height; - - SourceSurfaceCairo* source = static_cast(aSurface); - cairo_surface_t* sourcesurf = source->GetSurface(); - cairo_surface_t* blursurf; - cairo_surface_t* surf; + Rect extents(0, 0, width, height); - // We only use the A8 surface for blurred shadows. Unblurred shadows can just - // use the RGBA surface directly. - if (cairo_surface_get_type(sourcesurf) == CAIRO_SURFACE_TYPE_TEE) { - blursurf = cairo_tee_surface_index(sourcesurf, 0); - surf = cairo_tee_surface_index(sourcesurf, 1); - - MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE); - Rect extents(0, 0, width, height); - AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf), - extents, - cairo_image_surface_get_stride(blursurf), - aSigma); - blur.Blur(); - } else { - blursurf = sourcesurf; - surf = sourcesurf; + AlphaBoxBlur blur(extents, IntSize(0, 0), + AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)), + nullptr, nullptr); + if (!blur.GetData()) { + return; } - WillChange(); + IntSize blursize = blur.GetSize(); + cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(), + CAIRO_FORMAT_A8, + blursize.width, + blursize.height, + blur.GetStride()); + ClearSurfaceForUnboundedSource(aOperator); + // Draw the source surface into the surface we're going to blur. + SourceSurfaceCairo* source = static_cast(aSurface); + cairo_surface_t* surf = source->GetSurface(); + cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); + + cairo_t* ctx = cairo_create(blursurf); + + cairo_set_source(ctx, pat); + + IntRect blurrect = blur.GetRect(); + cairo_new_path(ctx); + cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height); + cairo_clip(ctx); + cairo_paint(ctx); + + cairo_destroy(ctx); + + // Blur the result, then use that blurred result as a mask to draw the shadow + // colour to the surface. + blur.Blur(); cairo_save(mContext); cairo_set_operator(mContext, GfxOpToCairoOp(aOperator)); cairo_identity_matrix(mContext); @@ -427,26 +440,33 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface, cairo_push_group(mContext); cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); - - // Now that the shadow has been drawn, we can draw the surface on top. - cairo_set_source_surface(mContext, surf, 0, 0); - cairo_new_path(mContext); - cairo_rectangle(mContext, 0, 0, width, height); - cairo_fill(mContext); cairo_pop_group_to_source(mContext); cairo_paint(mContext); + + // Now that the shadow has been drawn, we can draw the surface on top. + cairo_push_group(mContext); + cairo_new_path(mContext); + cairo_rectangle(mContext, 0, 0, width, height); + cairo_set_source(mContext, pat); + cairo_fill(mContext); + cairo_pop_group_to_source(mContext); } else { cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a); cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y); // Now that the shadow has been drawn, we can draw the surface on top. - cairo_set_source_surface(mContext, surf, 0, 0); + cairo_set_source(mContext, pat); cairo_new_path(mContext); cairo_rectangle(mContext, 0, 0, width, height); - cairo_fill(mContext); + cairo_clip(mContext); } + cairo_paint(mContext); + cairo_restore(mContext); + + cairo_pattern_destroy(pat); + cairo_surface_destroy(blursurf); } void @@ -801,49 +821,6 @@ DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& return true; } -TemporaryRef -DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const -{ - cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext), - GfxFormatToCairoContent(aFormat), - aSize.width, aSize.height); - - if (cairo_surface_status(similar)) { - return nullptr; - } - - // If we don't have a blur then we can use the RGBA mask and keep all the - // operations in graphics memory. - if (aSigma == 0.0F) { - RefPtr target = new DrawTargetCairo(); - target->InitAlreadyReferenced(similar, aSize); - return target; - } - - cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8, - aSize.width, - aSize.height); - - if (cairo_surface_status(blursurf)) { - return nullptr; - } - - cairo_surface_t* tee = cairo_tee_surface_create(blursurf); - cairo_surface_destroy(blursurf); - if (cairo_surface_status(tee)) { - cairo_surface_destroy(similar); - return nullptr; - } - - cairo_tee_surface_add(tee, similar); - cairo_surface_destroy(similar); - - RefPtr target = new DrawTargetCairo(); - target->InitAlreadyReferenced(tee, aSize); - return target; -} - bool DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize) { diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 27de74a1ebec..0f4edd5af64f 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -115,9 +115,6 @@ public: CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const; virtual TemporaryRef CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const; - virtual TemporaryRef - CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat, - float aSigma) const; virtual TemporaryRef CreateGradientStops(GradientStop *aStops, diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 8ec7dfa15d04..7e7e4bf13296 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -535,21 +535,8 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa dt->Flush(); } srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); - } else -#endif - if (aSurface->CairoSurface()) { - // If this is an xlib cairo surface we don't want to fetch it into memory - // because this is a major slow down. - NativeSurface surf; - surf.mFormat = format; - surf.mType = NATIVE_SURFACE_CAIRO_SURFACE; - surf.mSurface = aSurface->CairoSurface(); - srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf); - - // It's cheap enough to make a new one so we won't keep it around and - // keeping it creates a cycle. - return srcBuffer; } +#endif if (!srcBuffer) { nsRefPtr imgSurface = aSurface->GetAsImageSurface();