Skip to content

Commit

Permalink
Bug 1550710 - Make vector images enable high quality scaling for embe…
Browse files Browse the repository at this point in the history
…dded raster images. r=tnikkel

We did not pass FLAG_HIGH_QUALITY_SCALING down to the document used to
rasterize the SVG to a surface, resulting in embedded raster images to
not use high quality downscaling.

Differential Revision: https://phabricator.services.mozilla.com/D56422
  • Loading branch information
aosmond committed Jun 23, 2020
1 parent c2b6ecf commit 2e7fac5
Show file tree
Hide file tree
Showing 18 changed files with 59 additions and 12 deletions.
3 changes: 3 additions & 0 deletions image/VectorImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ bool SVGDrawingCallback::operator()(gfxContext* aContext,
if (!(mImageFlags & imgIContainer::FLAG_SYNC_DECODE)) {
renderDocFlags |= RenderDocumentFlags::AsyncDecodeImages;
}
if (mImageFlags & imgIContainer::FLAG_HIGH_QUALITY_SCALING) {
renderDocFlags |= RenderDocumentFlags::UseHighQualityScaling;
}

presShell->RenderDocument(svgRect, renderDocFlags,
NS_RGBA(0, 0, 0, 0), // transparent
Expand Down
3 changes: 3 additions & 0 deletions layout/base/PresShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,9 @@ nsresult PresShell::RenderDocument(const nsRect& aRect,
if (!(aFlags & RenderDocumentFlags::AsyncDecodeImages)) {
flags |= PaintFrameFlags::SyncDecodeImages;
}
if (aFlags & RenderDocumentFlags::UseHighQualityScaling) {
flags |= PaintFrameFlags::UseHighQualityScaling;
}
if (aFlags & RenderDocumentFlags::UseWidgetLayers) {
// We only support using widget layers on display root's with widgets.
nsView* view = rootFrame->GetView();
Expand Down
2 changes: 2 additions & 0 deletions layout/base/PresShell.h
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,8 @@ class PresShell final : public nsStubDocumentObserver,
* RenderDocumentFlags::IgnoreViewportScrolling is set or the document is in
* ignore viewport scrolling mode
* (PresShell::SetIgnoreViewportScrolling/IgnoringViewportScrolling).
* set RenderDocumentFlags::UseHighQualityScaling to enable downscale on
* decode for images.
* @param aBackgroundColor a background color to render onto
* @param aRenderedContext the gfxContext to render to. We render so that
* one CSS pixel in the source document is rendered to one unit in the current
Expand Down
1 change: 1 addition & 0 deletions layout/base/PresShellForwards.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ enum class RenderDocumentFlags {
AsyncDecodeImages = 1 << 4,
DocumentRelative = 1 << 5,
DrawWindowNotFlushing = 1 << 6,
UseHighQualityScaling = 1 << 7,
};

MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(RenderDocumentFlags)
Expand Down
3 changes: 3 additions & 0 deletions layout/base/nsLayoutUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3903,6 +3903,9 @@ nsresult nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext,
if (aFlags & (PaintFrameFlags::WidgetLayers | PaintFrameFlags::ToWindow)) {
builder->SetPaintingToWindow(true);
}
if (aFlags & PaintFrameFlags::UseHighQualityScaling) {
builder->SetUseHighQualityScaling(true);
}
if (aFlags & PaintFrameFlags::ForWebRender) {
builder->SetPaintingForWebRender(true);
}
Expand Down
1 change: 1 addition & 0 deletions layout/base/nsLayoutUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@ class nsLayoutUtils {
NoComposite = 0x100,
Compressed = 0x200,
ForWebRender = 0x400,
UseHighQualityScaling = 0x800,
};

/**
Expand Down
2 changes: 1 addition & 1 deletion layout/generic/nsBulletFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ ImgDrawResult BulletRenderer::CreateWebRenderCommandsForImage(
MOZ_RELEASE_ASSERT(mImage);

uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY;
if (aDisplayListBuilder->IsPaintingToWindow()) {
if (aDisplayListBuilder->UseHighQualityScaling()) {
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
Expand Down
4 changes: 2 additions & 2 deletions layout/generic/nsImageFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ void nsDisplayImage::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
if (aBuilder->ShouldSyncDecodeImages() || oldImageIsDifferent) {
flags |= imgIContainer::FLAG_SYNC_DECODE;
}
if (aBuilder->IsPaintingToWindow()) {
if (aBuilder->UseHighQualityScaling()) {
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}

Expand Down Expand Up @@ -1950,7 +1950,7 @@ bool nsDisplayImage::CreateWebRenderCommands(
if (aDisplayListBuilder->ShouldSyncDecodeImages() || oldImageIsDifferent) {
flags |= imgIContainer::FLAG_SYNC_DECODE;
}
if (aDisplayListBuilder->IsPaintingToWindow()) {
if (aDisplayListBuilder->UseHighQualityScaling()) {
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}

Expand Down
3 changes: 3 additions & 0 deletions layout/painting/nsCSSRendering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3022,6 +3022,9 @@ nsBackgroundLayerState nsCSSRendering::PrepareImageLayer(
if (aFlags & nsCSSRendering::PAINTBG_TO_WINDOW) {
irFlags |= nsImageRenderer::FLAG_PAINTING_TO_WINDOW;
}
if (aFlags & nsCSSRendering::PAINTBG_HIGH_QUALITY_SCALING) {
irFlags |= nsImageRenderer::FLAG_HIGH_QUALITY_SCALING;
}

nsBackgroundLayerState state(aForFrame, &aLayer.mImage, irFlags);
if (!state.mImageRenderer.PrepareImage()) {
Expand Down
7 changes: 6 additions & 1 deletion layout/painting/nsCSSRendering.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,12 @@ struct nsCSSRendering {
* When this flag is passed, painting will read properties of mask-image
* style, instead of background-image.
*/
PAINTBG_MASK_IMAGE = 0x08
PAINTBG_MASK_IMAGE = 0x08,
/**
* When this flag is passed, images are downscaled during decode. This
* is also implied by PAINTBG_TO_WINDOW.
*/
PAINTBG_HIGH_QUALITY_SCALING = 0x16,
};

struct PaintBGParams {
Expand Down
2 changes: 1 addition & 1 deletion layout/painting/nsCSSRenderingBorders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3624,7 +3624,7 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
}

uint32_t flags = imgIContainer::FLAG_ASYNC_NOTIFY;
if (aDisplayListBuilder->IsPaintingToWindow()) {
if (aDisplayListBuilder->UseHighQualityScaling()) {
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
Expand Down
7 changes: 6 additions & 1 deletion layout/painting/nsDisplayList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mIsInChromePresContext(false),
mSyncDecodeImages(false),
mIsPaintingToWindow(false),
mUseHighQualityScaling(false),
mIsPaintingForWebRender(false),
mIsCompositingCheap(false),
mContainsPluginItem(false),
Expand Down Expand Up @@ -599,6 +600,7 @@ void nsDisplayListBuilder::BeginFrame() {
mFrameToAnimatedGeometryRootMap.Put(mReferenceFrame, mRootAGR);

mIsPaintingToWindow = false;
mUseHighQualityScaling = false;
mIgnoreSuppression = false;
mInTransform = false;
mInFilter = false;
Expand Down Expand Up @@ -886,6 +888,9 @@ uint32_t nsDisplayListBuilder::GetBackgroundPaintFlags() {
if (mIsPaintingToWindow) {
flags |= nsCSSRendering::PAINTBG_TO_WINDOW;
}
if (mUseHighQualityScaling) {
flags |= nsCSSRendering::PAINTBG_HIGH_QUALITY_SCALING;
}
return flags;
}

Expand All @@ -896,7 +901,7 @@ uint32_t nsDisplayListBuilder::GetImageDecodeFlags() const {
} else {
flags |= imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
}
if (mIsPaintingToWindow) {
if (mIsPaintingToWindow || mUseHighQualityScaling) {
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
return flags;
Expand Down
11 changes: 11 additions & 0 deletions layout/painting/nsDisplayList.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,16 @@ class nsDisplayListBuilder {
*/
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
/**
* Call this if we're using high quality scaling for image decoding.
* It is also implied by IsPaintingToWindow.
*/
void SetUseHighQualityScaling(bool aUseHighQualityScaling) {
mUseHighQualityScaling = aUseHighQualityScaling;
}
bool UseHighQualityScaling() const {
return mIsPaintingToWindow || mUseHighQualityScaling;
}
/**
* Call this if we're doing painting for WebRender
*/
Expand Down Expand Up @@ -2014,6 +2024,7 @@ class nsDisplayListBuilder {
bool mIsInChromePresContext;
bool mSyncDecodeImages;
bool mIsPaintingToWindow;
bool mUseHighQualityScaling;
bool mIsPaintingForWebRender;
bool mIsCompositingCheap;
bool mContainsPluginItem;
Expand Down
6 changes: 4 additions & 2 deletions layout/painting/nsImageRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,8 @@ static uint32_t ConvertImageRendererToDrawFlags(uint32_t aImageRendererFlags) {
if (aImageRendererFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
drawFlags |= imgIContainer::FLAG_SYNC_DECODE;
}
if (aImageRendererFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
if (aImageRendererFlags & (nsImageRenderer::FLAG_PAINTING_TO_WINDOW |
nsImageRenderer::FLAG_HIGH_QUALITY_SCALING)) {
drawFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
return drawFlags;
Expand Down Expand Up @@ -571,7 +572,8 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
case StyleImage::Tag::Rect:
case StyleImage::Tag::Url: {
uint32_t containerFlags = imgIContainer::FLAG_ASYNC_NOTIFY;
if (mFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
if (mFlags & (nsImageRenderer::FLAG_PAINTING_TO_WINDOW |
nsImageRenderer::FLAG_HIGH_QUALITY_SCALING)) {
containerFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
if (mFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
Expand Down
6 changes: 5 additions & 1 deletion layout/painting/nsImageRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ class nsImageRenderer {
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::ImageContainer ImageContainer;

enum { FLAG_SYNC_DECODE_IMAGES = 0x01, FLAG_PAINTING_TO_WINDOW = 0x02 };
enum {
FLAG_SYNC_DECODE_IMAGES = 0x01,
FLAG_PAINTING_TO_WINDOW = 0x02,
FLAG_HIGH_QUALITY_SCALING = 0x04
};
enum FitType { CONTAIN, COVER };

nsImageRenderer(nsIFrame* aForFrame, const mozilla::StyleImage* aImage,
Expand Down
3 changes: 3 additions & 0 deletions layout/svg/nsSVGForeignObjectFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ void nsSVGForeignObjectFrame::PaintSVG(gfxContext& aContext,
if (aImgParams.imageFlags & imgIContainer::FLAG_SYNC_DECODE) {
flags |= PaintFrameFlags::SyncDecodeImages;
}
if (aImgParams.imageFlags & imgIContainer::FLAG_HIGH_QUALITY_SCALING) {
flags |= PaintFrameFlags::UseHighQualityScaling;
}
Unused << nsLayoutUtils::PaintFrame(
&aContext, kid, nsRegion(kidDirtyRect), NS_RGBA(0, 0, 0, 0),
nsDisplayListBuilderMode::Painting, flags);
Expand Down
5 changes: 3 additions & 2 deletions layout/xul/nsImageBoxFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ ImgDrawResult nsImageBoxFrame::CreateWebRenderCommands(
}

uint32_t containerFlags = imgIContainer::FLAG_ASYNC_NOTIFY;
if (aFlags & nsImageRenderer::FLAG_PAINTING_TO_WINDOW) {
if (aFlags & (nsImageRenderer::FLAG_PAINTING_TO_WINDOW |
nsImageRenderer::FLAG_HIGH_QUALITY_SCALING)) {
containerFlags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
}
if (aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
Expand Down Expand Up @@ -502,7 +503,7 @@ void nsDisplayXULImage::Paint(nsDisplayListBuilder* aBuilder,
uint32_t flags = imgIContainer::FLAG_SYNC_DECODE_IF_FAST;
if (aBuilder->ShouldSyncDecodeImages())
flags |= imgIContainer::FLAG_SYNC_DECODE;
if (aBuilder->IsPaintingToWindow())
if (aBuilder->UseHighQualityScaling())
flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;

ImgDrawResult result = static_cast<nsImageBoxFrame*>(mFrame)->PaintImage(
Expand Down
2 changes: 1 addition & 1 deletion layout/xul/tree/nsTreeBodyFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3372,7 +3372,7 @@ ImgDrawResult nsTreeBodyFrame::PaintImage(
opacity);
}

uint32_t drawFlags = aBuilder && aBuilder->IsPaintingToWindow()
uint32_t drawFlags = aBuilder && aBuilder->UseHighQualityScaling()
? imgIContainer::FLAG_HIGH_QUALITY_SCALING
: imgIContainer::FLAG_NONE;
result &= nsLayoutUtils::DrawImage(
Expand Down

0 comments on commit 2e7fac5

Please sign in to comment.