Bug 729562 - Make the SVG paint methods take an nsRenderingContext, and kill nsSVGRenderState. r=Bas.

This commit is contained in:
Jonathan Watt 2012-03-02 08:28:59 +00:00
parent 2034ac9bbc
commit 931f6fc216
33 changed files with 221 additions and 173 deletions

View File

@ -35,6 +35,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef MOZILLA_GFX_USERDATA_H_
#define MOZILLA_GFX_USERDATA_H_
#include <stdlib.h>
#include "mozilla/mozalloc.h"
@ -56,6 +58,9 @@ public:
/* Attaches untyped userData associated with key. destroy is called on destruction */
void Add(UserDataKey *key, void *userData, destroyFunc destroy)
{
// XXX we should really warn if user data with key has already been added,
// since in that case Get() will return the old user data!
// We could keep entries in a std::vector instead of managing it by hand
// but that would propagate an stl dependency out which we'd rather not
// do (see bug 666609). Plus, the entries array is expect to stay small
@ -69,7 +74,22 @@ public:
count++;
}
//XXX: we probably want to add a way to remove Keys
/* Remove and return user data associated with key, without destroying it */
void* Remove(UserDataKey *key)
{
for (int i=0; i<count; i++) {
if (key == entries[i].key) {
void *userData = entries[i].userData;
// decrement before looping so entries[i+1] doesn't read past the end:
--count;
for (;i<count; i++) {
entries[i] = entries[i+1];
}
return userData;
}
}
return NULL;
}
/* Retrives the userData for the associated key */
void *Get(UserDataKey *key)
@ -105,4 +125,4 @@ private:
}
}
#endif /* MOZILLA_GFX_USERDATA_H_ */

View File

@ -45,6 +45,7 @@
#include "nsColor.h"
#include "nsCoord.h"
#include "gfxContext.h"
#include "mozilla/gfx/UserData.h"
struct nsPoint;
class nsIntRegion;
@ -58,6 +59,9 @@ typedef enum {
class nsRenderingContext
{
typedef mozilla::gfx::UserData UserData;
typedef mozilla::gfx::UserDataKey UserDataKey;
public:
nsRenderingContext() : mP2A(0.) {}
// ~nsRenderingContext() {}
@ -136,6 +140,16 @@ public:
void DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY);
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
mUserData.Add(key, userData, destroy);
}
void *GetUserData(UserDataKey *key) {
return mUserData.Get(key);
}
void *RemoveUserData(UserDataKey *key) {
return mUserData.Remove(key);
}
protected:
PRInt32 GetMaxChunkLength();
@ -144,6 +158,8 @@ protected:
nsRefPtr<nsFontMetrics> mFontMetrics;
double mP2A; // cached app units per device pixel value
UserData mUserData;
};
#endif // NSRENDERINGCONTEXT__H__

View File

@ -47,7 +47,7 @@
#include "gfxMatrix.h"
class gfxContext;
class nsSVGRenderState;
class nsRenderingContext;
namespace mozilla {
class SVGAnimatedNumberList;
@ -70,7 +70,7 @@ public:
// Paint this frame - aDirtyRect is the area being redrawn, in frame
// offset pixel coordinates
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)=0;
// Check if this frame or children contain the given point,

View File

@ -56,7 +56,7 @@ NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSVGClipPathFrame)
nsresult
nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
nsSVGClipPathFrame::ClipPaint(nsRenderingContext* aContext,
nsIFrame* aParent,
const gfxMatrix &aMatrix)
{
@ -78,12 +78,11 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
bool isTrivial = IsTrivial();
nsAutoSVGRenderMode mode(aContext,
isTrivial ? nsSVGRenderState::CLIP
: nsSVGRenderState::CLIP_MASK);
SVGAutoRenderState mode(aContext,
isTrivial ? SVGAutoRenderState::CLIP
: SVGAutoRenderState::CLIP_MASK);
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
nsSVGClipPathFrame *clipPathFrame =
nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(nsnull);

View File

@ -40,6 +40,8 @@
#include "nsSVGContainerFrame.h"
#include "gfxMatrix.h"
class nsRenderingContext;
typedef nsSVGContainerFrame nsSVGClipPathFrameBase;
class nsSVGClipPathFrame : public nsSVGClipPathFrameBase
@ -55,7 +57,7 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// nsSVGClipPathFrame methods:
nsresult ClipPaint(nsSVGRenderState* aContext,
nsresult ClipPaint(nsRenderingContext* aContext,
nsIFrame* aParent,
const gfxMatrix &aMatrix);

View File

@ -164,7 +164,7 @@ nsSVGDisplayContainerFrame::RemoveFrame(ChildListID aListID,
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGDisplayContainerFrame::PaintSVG(nsSVGRenderState* aContext,
nsSVGDisplayContainerFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
{
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();

View File

@ -43,6 +43,8 @@
#include "gfxRect.h"
#include "gfxMatrix.h"
class nsRenderingContext;
typedef nsContainerFrame nsSVGContainerFrameBase;
class nsSVGContainerFrame : public nsSVGContainerFrameBase
@ -103,7 +105,7 @@ public:
nsIFrame* aPrevInFlow);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();

View File

@ -250,7 +250,7 @@ nsSVGFilterFrame::AttributeChanged(PRInt32 aNameSpaceID,
}
nsresult
nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsSVGFilterFrame::FilterPaint(nsRenderingContext *aContext,
nsIFrame *aTarget,
nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect *aDirtyRect)
@ -263,7 +263,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext,
nsRefPtr<gfxASurface> result;
nsresult rv = instance.get()->Render(getter_AddRefs(result));
if (NS_SUCCEEDED(rv) && result) {
nsSVGUtils::CompositeSurfaceMatrix(aContext->GetGfxContext(),
nsSVGUtils::CompositeSurfaceMatrix(aContext->ThebesContext(),
result, instance.get()->GetFilterSpaceToDeviceSpaceTransform(), 1.0);
}
return rv;

View File

@ -40,7 +40,7 @@
#include "nsRect.h"
#include "nsSVGContainerFrame.h"
class nsSVGRenderState;
class nsRenderingContext;
class nsSVGFilterPaintCallback;
typedef nsSVGContainerFrame nsSVGFilterFrameBase;
@ -58,7 +58,7 @@ public:
nsIAtom* aAttribute,
PRInt32 aModType);
nsresult FilterPaint(nsSVGRenderState *aContext,
nsresult FilterPaint(nsRenderingContext *aContext,
nsIFrame *aTarget, nsSVGFilterPaintCallback *aPaintCallback,
const nsIntRect* aDirtyRect);

View File

@ -364,8 +364,9 @@ nsSVGFilterInstance::BuildSourceImages()
if (!offscreen || offscreen->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
offscreen->SetDeviceOffset(gfxPoint(-mSurfaceRect.x, -mSurfaceRect.y));
nsSVGRenderState tmpState(offscreen);
nsRenderingContext tmpCtx;
tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), offscreen);
gfxMatrix userSpaceToFilterSpace = GetUserSpaceToFilterSpaceTransform();
gfxRect r(neededRect.x, neededRect.y, neededRect.width, neededRect.height);
@ -389,8 +390,8 @@ nsSVGFilterInstance::BuildSourceImages()
// code more complex while being hard to get right without introducing
// subtle bugs, and in practice it probably makes no real difference.)
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert();
tmpState.GetGfxContext()->Multiply(deviceToFilterSpace);
mPaintCallback->Paint(&tmpState, mTargetFrame, &dirty);
tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace);
mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty);
gfxContext copyContext(sourceColorAlpha);
copyContext.SetSource(offscreen);

View File

@ -40,7 +40,7 @@
#include "nsRect.h"
class nsIFrame;
class nsSVGRenderState;
class nsRenderingContext;
class nsSVGFilterPaintCallback {
public:
@ -54,7 +54,7 @@ public:
* system.
* @param aDirtyRect the dirty rect *in user space pixels*
*/
virtual void Paint(nsSVGRenderState *aContext, nsIFrame *aTarget,
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect *aDirtyRect) = 0;
};

View File

@ -209,7 +209,7 @@ ToCanvasBounds(const gfxRect &aUserspaceRect,
}
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
{
if (IsDisabled())
@ -222,9 +222,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
gfxMatrix matrixForChildren = GetCanvasTMForChildren();
gfxMatrix matrix = GetCanvasTM();
nsRenderingContext *ctx = aContext->GetRenderingContext(this);
if (!ctx || matrixForChildren.IsSingular()) {
if (matrixForChildren.IsSingular()) {
NS_WARNING("Can't render foreignObject element!");
return NS_ERROR_FAILURE;
}
@ -255,7 +253,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
return NS_OK;
}
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
gfx->Save();
@ -272,10 +270,10 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext,
gfx->Multiply(matrixForChildren);
PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM;
if (aContext->IsPaintingToWindow()) {
if (SVGAutoRenderState::IsPaintingToWindow(aContext)) {
flags |= nsLayoutUtils::PAINT_TO_WINDOW;
}
nsresult rv = nsLayoutUtils::PaintFrame(ctx, kid, nsRegion(kidDirtyRect),
nsresult rv = nsLayoutUtils::PaintFrame(aContext, kid, nsRegion(kidDirtyRect),
NS_RGBA(0,0,0,0), flags);
gfx->Restore();

View File

@ -46,6 +46,7 @@
#include "nsIPresShell.h"
#include "mozilla/Attributes.h"
class nsRenderingContext;
class nsSVGOuterSVGFrame;
typedef nsContainerFrame nsSVGForeignObjectFrameBase;
@ -121,7 +122,7 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext,
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();

View File

@ -323,14 +323,14 @@ nsSVGGlyphFrame::GetType() const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
{
if (!GetStyleVisibility()->IsVisible())
return NS_OK;
gfxContext *gfx = aContext->GetGfxContext();
PRUint16 renderMode = aContext->GetRenderMode();
gfxContext *gfx = aContext->ThebesContext();
PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext);
switch (GetStyleSVG()->mTextRendering) {
case NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED:
@ -341,7 +341,7 @@ nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext,
break;
}
if (renderMode != nsSVGRenderState::NORMAL) {
if (renderMode != SVGAutoRenderState::NORMAL) {
gfxMatrix matrix = gfx->CurrentMatrix();
SetupGlobalTransform(gfx);
@ -354,7 +354,7 @@ nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext,
else
gfx->SetFillRule(gfxContext::FILL_RULE_WINDING);
if (renderMode == nsSVGRenderState::CLIP_MASK) {
if (renderMode == SVGAutoRenderState::CLIP_MASK) {
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
DrawCharacters(&iter, gfx, gfxFont::GLYPH_FILL);
} else {

View File

@ -47,6 +47,7 @@
#include "gfxFont.h"
#include "nsTextFragment.h"
class nsRenderingContext;
class nsSVGTextFrame;
class nsSVGTextPathFrame;
class nsSVGGlyphFrame;
@ -172,7 +173,7 @@ public:
// nsISVGChildFrame interface:
// These four always use the global transform, even if NS_STATE_NONDISPLAY_CHILD
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext,
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD UpdateCoveredRegion();

View File

@ -50,6 +50,7 @@
using namespace mozilla;
class nsRenderingContext;
class nsSVGImageFrame;
class nsSVGImageListener MOZ_FINAL : public nsStubImageDecoderObserver
@ -90,7 +91,7 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
// nsSVGPathGeometryFrame methods:
@ -309,7 +310,7 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
//----------------------------------------------------------------------
// nsISVGChildFrame methods:
NS_IMETHODIMP
nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
{
nsresult rv = NS_OK;
@ -335,7 +336,7 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
}
if (mImageContainer) {
gfxContext* ctx = aContext->GetGfxContext();
gfxContext* ctx = aContext->ThebesContext();
gfxContextAutoSaveRestore autoRestorer(ctx);
if (GetStyleDisplay()->IsScrollableOverflow()) {
@ -404,7 +405,7 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
// That method needs our image to have a fixed native width & height,
// and that's not always true for TYPE_VECTOR images.
nsLayoutUtils::DrawSingleImage(
aContext->GetRenderingContext(this),
aContext,
mImageContainer,
nsLayoutUtils::GetGraphicsFilterForFrame(this),
destRect,
@ -414,7 +415,7 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderState *aContext,
rootSVGElem->ClearImageOverridePreserveAspectRatio();
} else { // mImageContainer->GetType() == TYPE_RASTER
nsLayoutUtils::DrawSingleUnscaledImage(
aContext->GetRenderingContext(this),
aContext,
mImageContainer,
nsLayoutUtils::GetGraphicsFilterForFrame(this),
nsPoint(0, 0),

View File

@ -83,7 +83,7 @@ nsSVGInnerSVGFrame::GetType() const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
{
gfxContextAutoSaveRestore autoSR;
@ -100,7 +100,7 @@ nsSVGInnerSVGFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
gfxMatrix clipTransform = parent->GetCanvasTM();
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
autoSR.SetContext(gfx);
gfxRect clipRect =
nsSVGUtils::GetClipRectForFrame(this, x, y, width, height);

View File

@ -40,6 +40,8 @@
#include "nsISVGSVGFrame.h"
#include "gfxMatrix.h"
class nsRenderingContext;
typedef nsSVGDisplayContainerFrame nsSVGInnerSVGFrameBase;
class nsSVGInnerSVGFrame : public nsSVGInnerSVGFrameBase,
@ -81,7 +83,7 @@ public:
PRInt32 aModType);
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect);
virtual void NotifySVGChanged(PRUint32 aFlags);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);

View File

@ -217,12 +217,11 @@ public:
: mBuilder(aBuilder), mInnerList(aInnerList), mFrame(aFrame),
mOffset(aOffset) {}
virtual void Paint(nsSVGRenderState *aContext, nsIFrame *aTarget,
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
{
nsRenderingContext* ctx = aContext->GetRenderingContext(aTarget);
nsRenderingContext::AutoPushTranslation push(ctx, -mOffset);
mInnerList->PaintForFrame(mBuilder, ctx, mFrame, nsDisplayList::PAINT_DEFAULT);
nsRenderingContext::AutoPushTranslation push(aContext, -mOffset);
mInnerList->PaintForFrame(mBuilder, aContext, mFrame, nsDisplayList::PAINT_DEFAULT);
}
private:
@ -283,7 +282,8 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfxContext* gfx = aCtx->ThebesContext();
gfxMatrix savedCTM = gfx->CurrentMatrix();
nsSVGRenderState svgContext(aCtx);
//SVGAutoRenderState autoRenderState(aCtx, SVGAutoRenderState::NORMAL);
nsRect userSpaceRect = GetNonSVGUserSpace(firstFrame) + aBuilder->ToReferenceFrame(firstFrame);
PRInt32 appUnitsPerDevPixel = aEffectsFrame->PresContext()->AppUnitsPerDevPixel();
@ -307,7 +307,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
*/
if (clipPathFrame && isTrivialClip) {
gfx->Save();
clipPathFrame->ClipPaint(&svgContext, aEffectsFrame, matrix);
clipPathFrame->ClipPaint(aCtx, aEffectsFrame, matrix);
}
/* Paint the child */
@ -315,7 +315,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
RegularFramePaintCallback paint(aBuilder, aInnerList, aEffectsFrame,
userSpaceRect.TopLeft());
nsIntRect r = (aDirtyRect - userSpaceRect.TopLeft()).ToOutsidePixels(appUnitsPerDevPixel);
filterFrame->FilterPaint(&svgContext, aEffectsFrame, &paint, &r);
filterFrame->FilterPaint(aCtx, aEffectsFrame, &paint, &r);
} else {
gfx->SetMatrix(savedCTM);
aInnerList->PaintForFrame(aBuilder, aCtx, aEffectsFrame,
@ -336,14 +336,14 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> maskSurface =
maskFrame ? maskFrame->ComputeMaskAlpha(&svgContext, aEffectsFrame,
maskFrame ? maskFrame->ComputeMaskAlpha(aCtx, aEffectsFrame,
matrix, opacity) : nsnull;
nsRefPtr<gfxPattern> clipMaskSurface;
if (clipPathFrame && !isTrivialClip) {
gfx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
nsresult rv = clipPathFrame->ClipPaint(&svgContext, aEffectsFrame, matrix);
nsresult rv = clipPathFrame->ClipPaint(aCtx, aEffectsFrame, matrix);
clipMaskSurface = gfx->PopGroup();
if (NS_SUCCEEDED(rv) && clipMaskSurface) {
@ -443,7 +443,8 @@ PaintFrameCallback::operator()(gfxContext* aContext,
mFrame->AddStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
nsSVGRenderState renderState(aContext);
nsRenderingContext context;
context.Init(mFrame->PresContext()->DeviceContext(), aContext);
aContext->Save();
// Clip to aFillRect so that we don't paint outside.
@ -475,7 +476,7 @@ PaintFrameCallback::operator()(gfxContext* aContext,
// Draw.
nsRect dirty(bbox.x, bbox.y, mPaintServerSize.width, mPaintServerSize.height);
nsLayoutUtils::PaintFrame(renderState.GetRenderingContext(mTarget), mFrame,
nsLayoutUtils::PaintFrame(&context, mFrame,
dirty, NS_RGBA(0, 0, 0, 0),
nsLayoutUtils::PAINT_IN_TRANSFORM |
nsLayoutUtils::PAINT_ALL_CONTINUATIONS);

View File

@ -122,7 +122,7 @@ nsSVGMarkerFrame::GetCanvasTM()
nsresult
nsSVGMarkerFrame::PaintMark(nsSVGRenderState *aContext,
nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext,
nsSVGPathGeometryFrame *aMarkedFrame,
nsSVGMark *aMark, float aStrokeWidth)
{
@ -148,7 +148,7 @@ nsSVGMarkerFrame::PaintMark(nsSVGRenderState *aContext,
mY = aMark->y;
mAutoAngle = aMark->angle;
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
if (GetStyleDisplay()->IsScrollableOverflow()) {
gfx->Save();

View File

@ -41,6 +41,7 @@
#include "gfxMatrix.h"
class gfxContext;
class nsRenderingContext;
class nsSVGPathGeometryFrame;
class nsIURI;
class nsIContent;
@ -87,7 +88,7 @@ public:
#endif
// nsSVGMarkerFrame methods:
nsresult PaintMark(nsSVGRenderState *aContext,
nsresult PaintMark(nsRenderingContext *aContext,
nsSVGPathGeometryFrame *aMarkedFrame,
nsSVGMark *aMark,
float aStrokeWidth);

View File

@ -54,7 +54,7 @@ NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
NS_IMPL_FRAMEARENA_HELPERS(nsSVGMaskFrame)
already_AddRefed<gfxPattern>
nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext,
nsIFrame* aParent,
const gfxMatrix &aMatrix,
float aOpacity)
@ -80,7 +80,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
gfxRect maskArea = nsSVGUtils::GetRelativeRect(units,
&mask->mLengthAttributes[nsSVGMaskElement::X], bbox, aParent);
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
gfx->Save();
nsSVGUtils::SetClipRect(gfx, aMatrix, maskArea);
@ -113,7 +113,8 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
return nsnull;
image->SetDeviceOffset(-clipExtents.TopLeft());
nsSVGRenderState tmpState(image);
nsRenderingContext tmpCtx;
tmpCtx.Init(this->PresContext()->DeviceContext(), image);
mMaskParent = aParent;
if (mMaskParentMatrix) {
@ -130,7 +131,7 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext,
SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
}
nsSVGUtils::PaintFrameWithEffects(&tmpState, nsnull, kid);
nsSVGUtils::PaintFrameWithEffects(&tmpCtx, nsnull, kid);
}
PRUint8 *data = image->Data();

View File

@ -42,6 +42,7 @@
#include "gfxMatrix.h"
class gfxContext;
class nsRenderingContext;
typedef nsSVGContainerFrame nsSVGMaskFrameBase;
@ -58,7 +59,7 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// nsSVGMaskFrame method:
already_AddRefed<gfxPattern> ComputeMaskAlpha(nsSVGRenderState *aContext,
already_AddRefed<gfxPattern> ComputeMaskAlpha(nsRenderingContext *aContext,
nsIFrame* aParent,
const gfxMatrix &aMatrix,
float aOpacity = 1.0f);

View File

@ -508,7 +508,7 @@ nsDisplaySVG::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
static_cast<nsSVGOuterSVGFrame*>(mFrame)->
Paint(aBuilder, *aCtx, mVisibleRect, ToReferenceFrame());
Paint(aBuilder, aCtx, mVisibleRect, ToReferenceFrame());
}
// helper
@ -585,14 +585,14 @@ nsSVGOuterSVGFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
void
nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
nsRenderingContext& aRenderingContext,
nsRenderingContext* aContext,
const nsRect& aDirtyRect, nsPoint aPt)
{
if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)
return;
// initialize Mozilla rendering context
aRenderingContext.PushState();
aContext->PushState();
nsRect viewportRect = GetContentRect();
nsPoint viewportOffset = aPt + viewportRect.TopLeft() - GetPosition();
@ -600,8 +600,8 @@ nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
nsRect clipRect;
clipRect.IntersectRect(aDirtyRect, viewportRect);
aRenderingContext.IntersectClip(clipRect);
aRenderingContext.Translate(viewportRect.TopLeft());
aContext->IntersectClip(clipRect);
aContext->Translate(viewportRect.TopLeft());
nsRect dirtyRect = clipRect - viewportOffset;
#if defined(DEBUG) && defined(SVG_DEBUG_PAINT_TIMING)
@ -610,30 +610,32 @@ nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
nsIntRect dirtyPxRect = dirtyRect.ToOutsidePixels(PresContext()->AppUnitsPerDevPixel());
nsSVGRenderState ctx(&aRenderingContext);
// Create an SVGAutoRenderState so we can call SetPaintingToWindow on
// it, but don't change the render mode:
SVGAutoRenderState state(aContext, SVGAutoRenderState::GetRenderMode(aContext));
if (aBuilder->IsPaintingToWindow()) {
ctx.SetPaintingToWindow(true);
state.SetPaintingToWindow(true);
}
#ifdef XP_MACOSX
if (mEnableBitmapFallback) {
// nquartz fallback paths, which svg tends to trigger, need
// a non-window context target
ctx.GetGfxContext()->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
aContext->ThebesContext()->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
}
#endif
nsSVGUtils::PaintFrameWithEffects(&ctx, &dirtyPxRect, this);
nsSVGUtils::PaintFrameWithEffects(aContext, &dirtyPxRect, this);
#ifdef XP_MACOSX
if (mEnableBitmapFallback) {
// show the surface we pushed earlier for fallbacks
ctx.GetGfxContext()->PopGroupToSource();
ctx.GetGfxContext()->Paint();
aContext->ThebesContext()->PopGroupToSource();
aContext->ThebesContext()->Paint();
}
if (ctx.GetGfxContext()->HasError() && !mEnableBitmapFallback) {
if (aContext->ThebesContext()->HasError() && !mEnableBitmapFallback) {
mEnableBitmapFallback = true;
// It's not really clear what area to invalidate here. We might have
// stuffed up rendering for the entire window in this paint pass,
@ -666,7 +668,7 @@ nsSVGOuterSVGFrame::Paint(const nsDisplayListBuilder* aBuilder,
printf("SVG Paint Timing: %f ms\n", (end-start)/1000.0);
#endif
aRenderingContext.PopState();
aContext->PopState();
}
nsSplittableType

View File

@ -110,7 +110,7 @@ public:
virtual nsIAtom* GetType() const;
void Paint(const nsDisplayListBuilder* aBuilder,
nsRenderingContext& aRenderingContext,
nsRenderingContext* aContext,
const nsRect& aDirtyRect, nsPoint aPt);
#ifdef DEBUG

View File

@ -108,7 +108,7 @@ nsSVGPathGeometryFrame::GetType() const
// nsISVGChildFrame methods
NS_IMETHODIMP
nsSVGPathGeometryFrame::PaintSVG(nsSVGRenderState *aContext,
nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
{
if (!GetStyleVisibility()->IsVisible())
@ -437,11 +437,11 @@ nsSVGPathGeometryFrame::MarkerProperties::GetMarkerEndFrame()
}
void
nsSVGPathGeometryFrame::Render(nsSVGRenderState *aContext)
nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext)
{
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
PRUint16 renderMode = aContext->GetRenderMode();
PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext);
switch (GetStyleSVG()->mShapeRendering) {
case NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED:
@ -458,7 +458,7 @@ nsSVGPathGeometryFrame::Render(nsSVGRenderState *aContext)
GeneratePath(gfx);
if (renderMode != nsSVGRenderState::NORMAL) {
if (renderMode != SVGAutoRenderState::NORMAL) {
gfx->Restore();
if (GetClipRule() == NS_STYLE_FILL_RULE_EVENODD)
@ -466,7 +466,7 @@ nsSVGPathGeometryFrame::Render(nsSVGRenderState *aContext)
else
gfx->SetFillRule(gfxContext::FILL_RULE_WINDING);
if (renderMode == nsSVGRenderState::CLIP_MASK) {
if (renderMode == SVGAutoRenderState::CLIP_MASK) {
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
gfx->Fill();
gfx->NewPath();

View File

@ -45,6 +45,7 @@
#include "nsGkAtoms.h"
#include "nsSVGGeometryFrame.h"
class nsRenderingContext;
class nsSVGMarkerFrame;
class nsSVGMarkerProperty;
@ -89,7 +90,7 @@ public:
protected:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState *aContext,
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHOD_(nsRect) GetCoveredRegion();
@ -110,7 +111,7 @@ protected:
const gfxMatrix *aOverrideTransform = nsnull);
private:
void Render(nsSVGRenderState *aContext);
void Render(nsRenderingContext *aContext);
struct MarkerProperties {
nsSVGMarkerProperty* mMarkerStart;

View File

@ -295,17 +295,18 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
if (!tmpSurface || tmpSurface->CairoStatus())
return NS_ERROR_FAILURE;
nsSVGRenderState tmpState(tmpSurface);
gfxContext* tmpContext = tmpState.GetGfxContext();
nsRenderingContext context;
context.Init(aSource->PresContext()->DeviceContext(), tmpSurface);
gfxContext* gfx = context.ThebesContext();
// Fill with transparent black
tmpContext->SetOperator(gfxContext::OPERATOR_CLEAR);
tmpContext->Paint();
tmpContext->SetOperator(gfxContext::OPERATOR_OVER);
gfx->SetOperator(gfxContext::OPERATOR_CLEAR);
gfx->Paint();
gfx->SetOperator(gfxContext::OPERATOR_OVER);
if (aGraphicOpacity != 1.0f) {
tmpContext->Save();
tmpContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
gfx->Save();
gfx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
}
// OK, now render -- note that we use "firstKid", which
@ -329,7 +330,7 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
}
nsSVGUtils::PaintFrameWithEffects(&tmpState, nsnull, kid);
nsSVGUtils::PaintFrameWithEffects(&context, nsnull, kid);
}
patternFrame->RemoveStateBits(NS_FRAME_DRAWING_AS_PAINTSERVER);
}
@ -337,9 +338,9 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface,
patternFrame->mSource = nsnull;
if (aGraphicOpacity != 1.0f) {
tmpContext->PopGroupToSource();
tmpContext->Paint(aGraphicOpacity);
tmpContext->Restore();
gfx->PopGroupToSource();
gfx->Paint(aGraphicOpacity);
gfx->Restore();
}
// caller now owns the surface

View File

@ -41,6 +41,8 @@
#include "gfxRect.h"
#include "gfxMatrix.h"
class nsRenderingContext;
typedef nsSVGGFrame nsSVGSwitchFrameBase;
class nsSVGSwitchFrame : public nsSVGSwitchFrameBase
@ -75,7 +77,7 @@ public:
#endif
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsRenderingContext* aContext, const nsIntRect *aDirtyRect);
NS_IMETHODIMP_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHODIMP_(nsRect) GetCoveredRegion();
NS_IMETHOD UpdateCoveredRegion();
@ -119,7 +121,7 @@ nsSVGSwitchFrame::GetType() const
}
NS_IMETHODIMP
nsSVGSwitchFrame::PaintSVG(nsSVGRenderState* aContext,
nsSVGSwitchFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
{
const nsStyleDisplay *display = mStyleContext->GetStyleDisplay();

View File

@ -219,7 +219,7 @@ nsSVGTextFrame::NotifyRedrawUnsuspended()
}
NS_IMETHODIMP
nsSVGTextFrame::PaintSVG(nsSVGRenderState* aContext,
nsSVGTextFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
{
UpdateGlyphPositioning(true);

View File

@ -43,6 +43,8 @@
#include "gfxRect.h"
#include "gfxMatrix.h"
class nsRenderingContext;
typedef nsSVGTextContainerFrame nsSVGTextFrameBase;
class nsSVGTextFrame : public nsSVGTextFrameBase
@ -87,7 +89,7 @@ public:
virtual void NotifyRedrawUnsuspended();
// Override these four to ensure that UpdateGlyphPositioning is called
// to bring glyph positions up to date
NS_IMETHOD PaintSVG(nsSVGRenderState* aContext,
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect);
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint & aPoint);
NS_IMETHOD UpdateCoveredRegion();

View File

@ -196,6 +196,56 @@ NS_SMILEnabled()
return gSMILEnabled;
}
// we only take the address of this:
static mozilla::gfx::UserDataKey sSVGAutoRenderStateKey;
SVGAutoRenderState::SVGAutoRenderState(nsRenderingContext *aContext,
RenderMode aMode)
: mContext(aContext)
, mOriginalRenderState(nsnull)
, mMode(aMode)
, mPaintingToWindow(false)
{
mOriginalRenderState = aContext->RemoveUserData(&sSVGAutoRenderStateKey);
// We always remove ourselves from aContext before it dies, so
// passing nsnull as the destroy function is okay.
aContext->AddUserData(&sSVGAutoRenderStateKey, this, nsnull);
}
SVGAutoRenderState::~SVGAutoRenderState()
{
mContext->RemoveUserData(&sSVGAutoRenderStateKey);
if (mOriginalRenderState) {
mContext->AddUserData(&sSVGAutoRenderStateKey, mOriginalRenderState, nsnull);
}
}
void
SVGAutoRenderState::SetPaintingToWindow(bool aPaintingToWindow)
{
mPaintingToWindow = aPaintingToWindow;
}
/* static */ SVGAutoRenderState::RenderMode
SVGAutoRenderState::GetRenderMode(nsRenderingContext *aContext)
{
void *state = aContext->GetUserData(&sSVGAutoRenderStateKey);
if (state) {
return static_cast<SVGAutoRenderState*>(state)->mMode;
}
return NORMAL;
}
/* static */ bool
SVGAutoRenderState::IsPaintingToWindow(nsRenderingContext *aContext)
{
void *state = aContext->GetUserData(&sSVGAutoRenderStateKey);
if (state) {
return static_cast<SVGAutoRenderState*>(state)->mPaintingToWindow;
}
return false;
}
nsSVGSVGElement*
nsSVGUtils::GetOuterSVGElement(nsSVGElement *aSVGElement)
{
@ -960,7 +1010,7 @@ nsSVGUtils::NotifyRedrawUnsuspended(nsIFrame *aFrame)
class SVGPaintCallback : public nsSVGFilterPaintCallback
{
public:
virtual void Paint(nsSVGRenderState *aContext, nsIFrame *aTarget,
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
{
nsISVGChildFrame *svgChildFrame = do_QueryFrame(aTarget);
@ -989,7 +1039,7 @@ public:
};
void
nsSVGUtils::PaintFrameWithEffects(nsSVGRenderState *aContext,
nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame *aFrame)
{
@ -1046,7 +1096,7 @@ nsSVGUtils::PaintFrameWithEffects(nsSVGRenderState *aContext,
if (opacity != 1.0f && CanOptimizeOpacity(aFrame))
opacity = 1.0f;
gfxContext *gfx = aContext->GetGfxContext();
gfxContext *gfx = aContext->ThebesContext();
bool complexEffects = false;
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
@ -1579,34 +1629,6 @@ nsSVGUtils::PathExtentsToMaxStrokeExtents(const gfxRect& aPathExtents,
// ----------------------------------------------------------------------
nsSVGRenderState::nsSVGRenderState(nsRenderingContext *aContext) :
mRenderMode(NORMAL), mRenderingContext(aContext), mPaintingToWindow(false)
{
mGfxContext = aContext->ThebesContext();
}
nsSVGRenderState::nsSVGRenderState(gfxContext *aContext) :
mRenderMode(NORMAL), mGfxContext(aContext), mPaintingToWindow(false)
{
}
nsSVGRenderState::nsSVGRenderState(gfxASurface *aSurface) :
mRenderMode(NORMAL), mPaintingToWindow(false)
{
mGfxContext = new gfxContext(aSurface);
}
nsRenderingContext*
nsSVGRenderState::GetRenderingContext(nsIFrame *aFrame)
{
if (!mRenderingContext) {
mRenderingContext = new nsRenderingContext();
mRenderingContext->Init(aFrame->PresContext()->DeviceContext(),
mGfxContext);
}
return mRenderingContext;
}
/* static */ bool
nsSVGUtils::RootSVGElementHasViewbox(const nsIContent *aRootSVGElem)
{

View File

@ -149,59 +149,30 @@ IsSVGWhitespace(PRUnichar aChar)
*/
bool NS_SMILEnabled();
// GRRR WINDOWS HATE HATE HATE
#undef CLIP_MASK
class nsSVGRenderState
class NS_STACK_CLASS SVGAutoRenderState
{
public:
enum RenderMode { NORMAL, CLIP, CLIP_MASK };
/**
* Render SVG to a legacy rendering context
*/
nsSVGRenderState(nsRenderingContext *aContext);
/**
* Render SVG to a modern rendering context
*/
nsSVGRenderState(gfxContext *aContext);
/**
* Render SVG to a temporary surface
*/
nsSVGRenderState(gfxASurface *aSurface);
SVGAutoRenderState(nsRenderingContext *aContext, RenderMode aMode);
~SVGAutoRenderState();
nsRenderingContext *GetRenderingContext(nsIFrame *aFrame);
gfxContext *GetGfxContext() { return mGfxContext; }
void SetPaintingToWindow(bool aPaintingToWindow);
void SetRenderMode(RenderMode aMode) { mRenderMode = aMode; }
RenderMode GetRenderMode() { return mRenderMode; }
void SetPaintingToWindow(bool aPaintingToWindow) {
mPaintingToWindow = aPaintingToWindow;
}
bool IsPaintingToWindow() { return mPaintingToWindow; }
static RenderMode GetRenderMode(nsRenderingContext *aContext);
static bool IsPaintingToWindow(nsRenderingContext *aContext);
private:
RenderMode mRenderMode;
nsRefPtr<nsRenderingContext> mRenderingContext;
nsRefPtr<gfxContext> mGfxContext;
bool mPaintingToWindow;
nsRenderingContext *mContext;
void *mOriginalRenderState;
RenderMode mMode;
bool mPaintingToWindow;
};
class nsAutoSVGRenderMode
{
public:
nsAutoSVGRenderMode(nsSVGRenderState *aState,
nsSVGRenderState::RenderMode aMode) : mState(aState) {
mOriginalMode = aState->GetRenderMode();
aState->SetRenderMode(aMode);
}
~nsAutoSVGRenderMode() { mState->SetRenderMode(mOriginalMode); }
private:
nsSVGRenderState *mState;
nsSVGRenderState::RenderMode mOriginalMode;
};
#define NS_ISVGFILTERPROPERTY_IID \
{ 0x9744ee20, 0x1bcf, 0x4c62, \
@ -401,7 +372,7 @@ public:
/* Paint SVG frame with SVG effects - aDirtyRect is the area being
* redrawn, in device pixel coordinates relative to the outer svg */
static void
PaintFrameWithEffects(nsSVGRenderState *aContext,
PaintFrameWithEffects(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame *aFrame);