mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1366875. Apply the same sync decoding heuristic to SVG <image> as we do to HTML <img>. r=mats
--HG-- rename : layout/svg/nsSVGImageFrame.cpp => layout/svg/nsSVGImageFrame.h
This commit is contained in:
parent
226f6b9185
commit
c8ba76db41
@ -26,6 +26,7 @@
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsImageFrame.h"
|
||||
#include "nsSVGImageFrame.h"
|
||||
|
||||
#include "nsIPresShell.h"
|
||||
|
||||
@ -1180,8 +1181,9 @@ nsImageLoadingContent::CancelPendingEvent()
|
||||
RefPtr<imgRequestProxy>&
|
||||
nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
|
||||
{
|
||||
nsImageFrame* frame = do_QueryFrame(GetOurPrimaryFrame());
|
||||
if (frame) {
|
||||
nsImageFrame* imageFrame = do_QueryFrame(GetOurPrimaryFrame());
|
||||
nsSVGImageFrame* svgImageFrame = do_QueryFrame(GetOurPrimaryFrame());
|
||||
if (imageFrame || svgImageFrame) {
|
||||
// Detect JavaScript-based animations created by changing the |src|
|
||||
// attribute on a timer.
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
@ -1191,7 +1193,12 @@ nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
|
||||
|
||||
// If the length of time between request changes is less than the threshold,
|
||||
// then force sync decoding to eliminate flicker from the animation.
|
||||
frame->SetForceSyncDecoding(now - mMostRecentRequestChange < threshold);
|
||||
bool forceSync = (now - mMostRecentRequestChange < threshold);
|
||||
if (imageFrame) {
|
||||
imageFrame->SetForceSyncDecoding(forceSync);
|
||||
} else {
|
||||
svgImageFrame->SetForceSyncDecoding(forceSync);
|
||||
}
|
||||
|
||||
mMostRecentRequestChange = now;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ EXPORTS += [
|
||||
'nsSVGEffects.h',
|
||||
'nsSVGFilterInstance.h',
|
||||
'nsSVGForeignObjectFrame.h',
|
||||
'nsSVGImageFrame.h',
|
||||
'nsSVGIntegrationUtils.h',
|
||||
'nsSVGUtils.h',
|
||||
'SVGImageContext.h',
|
||||
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsSVGImageFrame.h"
|
||||
|
||||
// Keep in (case-insensitive) order:
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
@ -29,97 +31,11 @@ using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
class nsSVGImageFrame;
|
||||
|
||||
class nsSVGImageListener final : public imgINotificationObserver
|
||||
{
|
||||
public:
|
||||
explicit nsSVGImageListener(nsSVGImageFrame *aFrame);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||
|
||||
void SetFrame(nsSVGImageFrame *frame) { mFrame = frame; }
|
||||
|
||||
private:
|
||||
~nsSVGImageListener() {}
|
||||
|
||||
nsSVGImageFrame *mFrame;
|
||||
};
|
||||
|
||||
class nsSVGImageFrame final
|
||||
: public SVGGeometryFrame
|
||||
, public nsIReflowCallback
|
||||
{
|
||||
friend nsIFrame*
|
||||
NS_NewSVGImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
protected:
|
||||
explicit nsSVGImageFrame(nsStyleContext* aContext)
|
||||
: SVGGeometryFrame(aContext, LayoutFrameType::SVGImage)
|
||||
, mReflowCallbackPosted(false)
|
||||
{
|
||||
EnableVisibilityTracking();
|
||||
}
|
||||
|
||||
virtual ~nsSVGImageFrame();
|
||||
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
// nsSVGDisplayableFrame interface:
|
||||
virtual void PaintSVG(gfxContext& aContext,
|
||||
const gfxMatrix& aTransform,
|
||||
imgDrawingParams& aImgParams,
|
||||
const nsIntRect* aDirtyRect = nullptr) override;
|
||||
virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
|
||||
virtual void ReflowSVG() override;
|
||||
|
||||
// SVGGeometryFrame methods:
|
||||
virtual uint16_t GetHitTestFlags() override;
|
||||
|
||||
// nsIFrame interface:
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
|
||||
void OnVisibilityChange(Visibility aNewVisibility,
|
||||
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("SVGImage"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsIReflowCallback
|
||||
virtual bool ReflowFinished() override;
|
||||
virtual void ReflowCallbackCanceled() override;
|
||||
|
||||
private:
|
||||
gfx::Matrix GetRasterImageTransform(int32_t aNativeWidth,
|
||||
int32_t aNativeHeight);
|
||||
gfx::Matrix GetVectorImageTransform();
|
||||
bool TransformContextForPainting(gfxContext* aGfxContext,
|
||||
const gfxMatrix& aTransform);
|
||||
|
||||
nsCOMPtr<imgINotificationObserver> mListener;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
|
||||
bool mReflowCallbackPosted;
|
||||
|
||||
friend class nsSVGImageListener;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
// ---------------------------------------------------------------------
|
||||
// nsQueryFrame methods
|
||||
NS_QUERYFRAME_HEAD(nsSVGImageFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsSVGImageFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(SVGGeometryFrame)
|
||||
|
||||
nsIFrame*
|
||||
NS_NewSVGImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
@ -397,6 +313,11 @@ nsSVGImageFrame::PaintSVG(gfxContext& aContext,
|
||||
dirtyRect.MoveBy(-rootRect.TopLeft());
|
||||
}
|
||||
|
||||
uint32_t flags = aImgParams.imageFlags;
|
||||
if (mForceSyncDecoding) {
|
||||
flags |= imgIContainer::FLAG_SYNC_DECODE;
|
||||
}
|
||||
|
||||
if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
// Package up the attributes of this image element which can override the
|
||||
// attributes of mImageContainer's internal SVG document. The 'width' &
|
||||
@ -426,7 +347,7 @@ nsSVGImageFrame::PaintSVG(gfxContext& aContext,
|
||||
destRect,
|
||||
aDirtyRect ? dirtyRect : destRect,
|
||||
context,
|
||||
aImgParams.imageFlags);
|
||||
flags);
|
||||
} else { // mImageContainer->GetType() == TYPE_RASTER
|
||||
aImgParams.result &= nsLayoutUtils::DrawSingleUnscaledImage(
|
||||
aContext,
|
||||
@ -435,7 +356,7 @@ nsSVGImageFrame::PaintSVG(gfxContext& aContext,
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(this),
|
||||
nsPoint(0, 0),
|
||||
aDirtyRect ? &dirtyRect : nullptr,
|
||||
aImgParams.imageFlags);
|
||||
flags);
|
||||
}
|
||||
|
||||
if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
|
||||
|
131
layout/svg/nsSVGImageFrame.h
Normal file
131
layout/svg/nsSVGImageFrame.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __NS_SVGIMAGEFRAME_H__
|
||||
#define __NS_SVGIMAGEFRAME_H__
|
||||
|
||||
// Keep in (case-insensitive) order:
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "imgINotificationObserver.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "SVGGeometryFrame.h"
|
||||
#include "SVGImageContext.h"
|
||||
#include "mozilla/dom/SVGImageElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIReflowCallback.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
class nsSVGImageFrame;
|
||||
|
||||
class nsSVGImageListener final : public imgINotificationObserver
|
||||
{
|
||||
public:
|
||||
explicit nsSVGImageListener(nsSVGImageFrame *aFrame);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||
|
||||
void SetFrame(nsSVGImageFrame *frame) { mFrame = frame; }
|
||||
|
||||
private:
|
||||
~nsSVGImageListener() {}
|
||||
|
||||
nsSVGImageFrame *mFrame;
|
||||
};
|
||||
|
||||
class nsSVGImageFrame final
|
||||
: public SVGGeometryFrame
|
||||
, public nsIReflowCallback
|
||||
{
|
||||
friend nsIFrame*
|
||||
NS_NewSVGImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
protected:
|
||||
explicit nsSVGImageFrame(nsStyleContext* aContext)
|
||||
: SVGGeometryFrame(aContext, LayoutFrameType::SVGImage)
|
||||
, mReflowCallbackPosted(false)
|
||||
, mForceSyncDecoding(false)
|
||||
{
|
||||
EnableVisibilityTracking();
|
||||
}
|
||||
|
||||
virtual ~nsSVGImageFrame();
|
||||
|
||||
public:
|
||||
NS_DECL_QUERYFRAME_TARGET(nsSVGImageFrame)
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
// nsSVGDisplayableFrame interface:
|
||||
virtual void PaintSVG(gfxContext& aContext,
|
||||
const gfxMatrix& aTransform,
|
||||
imgDrawingParams& aImgParams,
|
||||
const nsIntRect* aDirtyRect = nullptr) override;
|
||||
virtual nsIFrame* GetFrameForPoint(const gfxPoint& aPoint) override;
|
||||
virtual void ReflowSVG() override;
|
||||
|
||||
// SVGGeometryFrame methods:
|
||||
virtual uint16_t GetHitTestFlags() override;
|
||||
|
||||
// nsIFrame interface:
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
|
||||
void OnVisibilityChange(Visibility aNewVisibility,
|
||||
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent,
|
||||
nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("SVGImage"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
// nsIReflowCallback
|
||||
virtual bool ReflowFinished() override;
|
||||
virtual void ReflowCallbackCanceled() override;
|
||||
|
||||
/// Always sync decode our image when painting if @aForce is true.
|
||||
void SetForceSyncDecoding(bool aForce) { mForceSyncDecoding = aForce; }
|
||||
|
||||
private:
|
||||
gfx::Matrix GetRasterImageTransform(int32_t aNativeWidth,
|
||||
int32_t aNativeHeight);
|
||||
gfx::Matrix GetVectorImageTransform();
|
||||
bool TransformContextForPainting(gfxContext* aGfxContext,
|
||||
const gfxMatrix& aTransform);
|
||||
|
||||
nsCOMPtr<imgINotificationObserver> mListener;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
|
||||
bool mReflowCallbackPosted;
|
||||
bool mForceSyncDecoding;
|
||||
|
||||
friend class nsSVGImageListener;
|
||||
};
|
||||
|
||||
#endif // __NS_SVGIMAGEFRAME_H__
|
Loading…
Reference in New Issue
Block a user