Bug 1269971 - Part 2. From ClipBackgroundByText to GenerateAndPushTextMask; r=jfkthame,mtseng

MozReview-Commit-ID: 1PK2Huytq3i
This commit is contained in:
CJKu
2016-05-13 00:08:41 +08:00
parent 17721f6781
commit b5b879d00c
3 changed files with 52 additions and 24 deletions

View File

@@ -493,30 +493,59 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
}
static void
ClipBackgroundByText(nsIFrame* aFrame, nsRenderingContext* aContext,
GenerateAndPushTextMask(nsIFrame* aFrame, nsRenderingContext* aContext,
const nsRect& aFillRect)
{
// The main function of enabling background-clip:text property value.
// When a nsDisplayBackgroundImage detects "text" bg-clip style, it will call
// this function to
// 1. Ask every text frame objects in aFrame puts glyph paths into aContext.
// 2. Clip aContext.
//
// Then, nsDisplayBackgroundImage paints bg-images into this clipped region,
// so we get images embedded in text shape!
// 1. Generate a mask by all descendant text frames
// 2. Push the generated mask into aContext.
gfxContext* ctx = aContext->ThebesContext();
gfxContextMatrixAutoSaveRestore save(ctx);
gfxRect bounds = nsLayoutUtils::RectToGfxRect(aFillRect, aFrame->PresContext()->AppUnitsPerDevPixel());
ctx->SetMatrix(ctx->CurrentMatrix().Translate(bounds.TopLeft()));
ctx->NewPath();
gfxContext* sourceCtx = aContext->ThebesContext();
gfxRect bounds =
nsLayoutUtils::RectToGfxRect(aFillRect,
aFrame->PresContext()->AppUnitsPerDevPixel());
nsLayoutUtils::PaintFrame(aContext, aFrame,
// Evaluate required surface size.
IntRect drawRect;
{
gfxContextMatrixAutoSaveRestore matRestore(sourceCtx);
sourceCtx->SetMatrix(gfxMatrix());
gfxRect clipRect = sourceCtx->GetClipExtents();
drawRect = RoundedOut(ToRect(clipRect));
}
// Create a mask surface.
RefPtr<DrawTarget> sourceTarget = sourceCtx->GetDrawTarget();
RefPtr<DrawTarget> maskDT =
sourceTarget->CreateSimilarDrawTarget(drawRect.Size(),
SurfaceFormat::A8);
if (!maskDT) {
NS_ABORT_OOM(drawRect.width * drawRect.height);
}
RefPtr<gfxContext> maskCtx = gfxContext::ForDrawTargetWithTransform(maskDT);
gfxMatrix currentMatrix = sourceCtx->CurrentMatrix();
maskCtx->SetMatrix(gfxMatrix::Translation(bounds.TopLeft()) *
currentMatrix *
gfxMatrix::Translation(-drawRect.TopLeft()));
// Shade text shape into mask A8 surface.
nsRenderingContext rc(maskCtx);
nsLayoutUtils::PaintFrame(&rc, aFrame,
nsRect(nsPoint(0, 0), aFrame->GetSize()),
NS_RGB(255, 255, 255),
nsDisplayListBuilderMode::GENERATE_GLYPH);
ctx->Clip();
// Push the generated mask into aContext, so that the caller can pop and
// blend with it.
Matrix maskTransform = ToMatrix(currentMatrix) *
Matrix::Translation(-drawRect.x, -drawRect.y);
maskTransform.Invert();
RefPtr<SourceSurface> maskSurface = maskDT->Snapshot();
sourceCtx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 1.0, maskSurface, maskTransform);
}
/* static */ void
@@ -2912,8 +2941,7 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
uint8_t clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
ctx->Save();
ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect);
}
image::DrawResult result =
@@ -2924,7 +2952,7 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
CompositionOp::OP_OVER);
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
ctx->Restore();
ctx->PopGroupAndBlend();
}
nsDisplayBackgroundGeometry::UpdateDrawResult(this, result);
@@ -3344,10 +3372,10 @@ nsDisplayBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
if (clip == NS_STYLE_IMAGELAYER_CLIP_TEXT) {
gfxContextAutoSaveRestore save(ctx);
ClipBackgroundByText(mFrame, aCtx, mBackgroundRect);
GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect);
ctx->SetColor(mColor);
ctx->Fill();
ctx->PopGroupAndBlend();
return;
}

View File

@@ -4798,10 +4798,7 @@ nsDisplayText::Paint(nsDisplayListBuilder* aBuilder,
params.dirtyRect = extraVisible;
nsTextFrame::DrawPathCallbacks callbacks;
if (aBuilder->IsForGenerateGlyphMask()) {
params.callbacks = &callbacks;
}
params.generateTextMask = aBuilder->IsForGenerateGlyphMask();
f->PaintText(params, *this, mOpacity);
}
@@ -6595,7 +6592,9 @@ nsTextFrame::PaintText(const PaintTextParams& aParams,
}
}
nscolor foregroundColor = textPaintStyle.GetTextColor();
nscolor foregroundColor = aParams.generateTextMask
? NS_RGBA(0, 0, 0, 255)
: textPaintStyle.GetTextColor();
if (aOpacity != 1.0f) {
gfx::Color gfxColor = gfx::Color::FromABGR(foregroundColor);
gfxColor.a *= aOpacity;

View File

@@ -392,6 +392,7 @@ public:
LayoutDeviceRect dirtyRect;
gfxTextContextPaint* contextPaint = nullptr;
DrawPathCallbacks* callbacks = nullptr;
bool generateTextMask = false;
explicit PaintTextParams(gfxContext* aContext) : context(aContext) {}
};