This is an automated email from the git hooks/post-receive script.
richard pushed a commit to branch geckoview-102.3.0esr-12.0-1 in repository tor-browser.
commit 344e8654b59ec8b052cb6a2ab1bf28d37d81d559 Author: Jonathan Kew jkew@mozilla.com AuthorDate: Tue Jul 5 07:55:56 2022 +0000
Bug 1777209 - Use DrawSurface rather than FillRect to paint <canvas>, and don't use EXTEND_PAD when writing to PDF. r=jrmuizel, a=RyanVM
Differential Revision: https://phabricator.services.mozilla.com/D150601 --- gfx/2d/DrawTargetCairo.cpp | 12 ++++++++- layout/generic/nsHTMLCanvasFrame.cpp | 50 ++++++++++++++++++++---------------- layout/reftests/bugs/reftest.list | 2 +- 3 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index e0e7607936de7..1877ddc2ba226 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -884,7 +884,17 @@ void DrawTargetCairo::DrawSurface(SourceSurface* aSurface, const Rect& aDest, cairo_pattern_set_matrix(pat, &src_mat); cairo_pattern_set_filter( pat, GfxSamplingFilterToCairoFilter(aSurfOptions.mSamplingFilter)); - cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD); + // For PDF output, we avoid using EXTEND_PAD here because floating-point + // error accumulation may lead cairo_pdf_surface to conclude that padding + // is needed due to an apparent one- or two-pixel mismatch between source + // pattern and destination rect sizes when we're rendering a pdf.js page, + // and this forces undesirable fallback to the rasterization codepath + // instead of simply replaying the recording. + // (See bug 1777209.) + cairo_pattern_set_extend( + pat, cairo_surface_get_type(mSurface) == CAIRO_SURFACE_TYPE_PDF + ? CAIRO_EXTEND_NONE + : CAIRO_EXTEND_PAD);
cairo_set_antialias(mContext, GfxAntialiasToCairoAntialias(aOptions.mAntialiasMode)); diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index bfb9f1f71c034..09d6358e8e0cd 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -298,19 +298,20 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem { nsRect dest = nsLayoutUtils::ComputeObjectDestRect( area, intrinsicSize, intrinsicRatio, f->StylePosition());
- gfxRect destGFXRect = presContext->AppUnitsToGfxUnits(dest); - - // Transform the canvas into the right place - gfxPoint p = destGFXRect.TopLeft(); - Matrix transform = Matrix::Translation(p.x, p.y); - transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width, - destGFXRect.Height() / canvasSizeInPx.height); gfxContextMatrixAutoSaveRestore saveMatrix(aCtx);
- aCtx->SetMatrix( - gfxUtils::SnapTransformTranslation(aCtx->CurrentMatrix(), nullptr)); - if (RefPtrlayers::Image image = canvas->GetAsImage()) { + gfxRect destGFXRect = presContext->AppUnitsToGfxUnits(dest); + + // Transform the canvas into the right place + gfxPoint p = destGFXRect.TopLeft(); + Matrix transform = Matrix::Translation(p.x, p.y); + transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width, + destGFXRect.Height() / canvasSizeInPx.height); + + aCtx->SetMatrix( + gfxUtils::SnapTransformTranslation(aCtx->CurrentMatrix(), nullptr)); + RefPtrgfx::SourceSurface surface = image->GetAsSourceSurface(); if (!surface || !surface->IsValid()) { return; @@ -338,23 +339,28 @@ class nsDisplayCanvas final : public nsPaintedDisplayItem { } renderer->FirePreTransactionCallback(); const auto snapshot = renderer->BorrowSnapshot(); - if (!snapshot) return; + if (!snapshot) { + return; + } const auto& surface = snapshot->mSurf; - - transform = gfxUtils::SnapTransform( - transform, gfxRect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height), - nullptr); + DrawTarget& dt = *aCtx->GetDrawTarget(); + gfx::Rect destRect = + NSRectToSnappedRect(dest, presContext->AppUnitsPerDevPixel(), dt);
if (!renderer->YIsDown()) { - // y-flip - transform.PreTranslate(0.0f, canvasSizeInPx.height).PreScale(1.0f, -1.0f); + // Calculate y-coord that is as far below the bottom of destGFXRect as + // the origin was above the top, then reflect about that. + float y = destRect.Y() + destRect.YMost(); + Matrix transform = Matrix::Translation(0.0f, y).PreScale(1.0f, -1.0f); + aCtx->Multiply(transform); } - aCtx->Multiply(transform);
- aCtx->GetDrawTarget()->FillRect( - Rect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height), - SurfacePattern(surface, ExtendMode::CLAMP, Matrix(), - nsLayoutUtils::GetSamplingFilterForFrame(f))); + const auto& srcRect = surface->GetRect(); + dt.DrawSurface( + surface, destRect, + Rect(float(srcRect.X()), float(srcRect.Y()), float(srcRect.Width()), + float(srcRect.Height())), + DrawSurfaceOptions(nsLayoutUtils::GetSamplingFilterForFrame(f)));
renderer->FireDidTransactionCallback(); renderer->ResetDirty(); diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 557cefccf4f2b..03dcde776fc1b 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1567,7 +1567,7 @@ random-if(winWidget) fuzzy(0-1,0-480) needs-focus == 598726-1.html 598726-1-ref. # the idealized rendering. As such we assume we fail the old test, and pass the # new test. See bug 1580534 for more details. fuzzy-if(Android,0-8,0-20) fails-if(!useDrawSnapshot) == 602200-3.html 602200-3-ref.html -fuzzy-if(useDrawSnapshot,255-255,44-44) == 1580534.html 1580534-ref.html +fuzzy-if(useDrawSnapshot,255-255,34-34) == 1580534.html 1580534-ref.html == 602200-4.html 602200-4-ref.html == 603423-1.html 603423-1-ref.html == 604737.html 604737-ref.html