layout/svg/nsSVGMarkerFrame.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 // Main header first:
     7 #include "nsSVGMarkerFrame.h"
     9 // Keep others in (case-insensitive) order:
    10 #include "gfxContext.h"
    11 #include "nsRenderingContext.h"
    12 #include "nsSVGEffects.h"
    13 #include "mozilla/dom/SVGMarkerElement.h"
    14 #include "nsSVGPathGeometryElement.h"
    15 #include "nsSVGPathGeometryFrame.h"
    17 using namespace mozilla::dom;
    18 using namespace mozilla::gfx;
    20 nsIFrame*
    21 NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    22 {
    23   return new (aPresShell) nsSVGMarkerFrame(aContext);
    24 }
    26 NS_IMPL_FRAMEARENA_HELPERS(nsSVGMarkerFrame)
    28 //----------------------------------------------------------------------
    29 // nsIFrame methods:
    31 nsresult
    32 nsSVGMarkerFrame::AttributeChanged(int32_t  aNameSpaceID,
    33                                    nsIAtom* aAttribute,
    34                                    int32_t  aModType)
    35 {
    36   if (aNameSpaceID == kNameSpaceID_None &&
    37       (aAttribute == nsGkAtoms::markerUnits ||
    38        aAttribute == nsGkAtoms::refX ||
    39        aAttribute == nsGkAtoms::refY ||
    40        aAttribute == nsGkAtoms::markerWidth ||
    41        aAttribute == nsGkAtoms::markerHeight ||
    42        aAttribute == nsGkAtoms::orient ||
    43        aAttribute == nsGkAtoms::preserveAspectRatio ||
    44        aAttribute == nsGkAtoms::viewBox)) {
    45     nsSVGEffects::InvalidateDirectRenderingObservers(this);
    46   }
    48   return nsSVGMarkerFrameBase::AttributeChanged(aNameSpaceID,
    49                                                 aAttribute, aModType);
    50 }
    52 #ifdef DEBUG
    53 void
    54 nsSVGMarkerFrame::Init(nsIContent* aContent,
    55                        nsIFrame* aParent,
    56                        nsIFrame* aPrevInFlow)
    57 {
    58   NS_ASSERTION(aContent->IsSVG(nsGkAtoms::marker), "Content is not an SVG marker");
    60   nsSVGMarkerFrameBase::Init(aContent, aParent, aPrevInFlow);
    61 }
    62 #endif /* DEBUG */
    64 nsIAtom *
    65 nsSVGMarkerFrame::GetType() const
    66 {
    67   return nsGkAtoms::svgMarkerFrame;
    68 }
    70 //----------------------------------------------------------------------
    71 // nsSVGContainerFrame methods:
    73 gfxMatrix
    74 nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
    75 {
    76   NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame");
    78   if (mInUse2) {
    79     // We're going to be bailing drawing the marker, so return an identity.
    80     return gfxMatrix();
    81   }
    83   SVGMarkerElement *content = static_cast<SVGMarkerElement*>(mContent);
    85   mInUse2 = true;
    86   gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor, aTransformRoot);
    87   mInUse2 = false;
    89   Matrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY,
    90                                                 mAutoAngle, mIsStart);
    91   Matrix viewBoxTM = content->GetViewBoxTransform();
    93   return ThebesMatrix(viewBoxTM * markerTM) * markedTM;
    94 }
    96 static nsIFrame*
    97 GetAnonymousChildFrame(nsIFrame* aFrame)
    98 {
    99   nsIFrame* kid = aFrame->GetFirstPrincipalChild();
   100   MOZ_ASSERT(kid && kid->GetType() == nsGkAtoms::svgMarkerAnonChildFrame,
   101              "expected to find anonymous child of marker frame");
   102   return kid;
   103 }
   105 nsresult
   106 nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext,
   107                             nsSVGPathGeometryFrame *aMarkedFrame,
   108                             nsSVGMark *aMark, float aStrokeWidth)
   109 {
   110   // If the flag is set when we get here, it means this marker frame
   111   // has already been used painting the current mark, and the document
   112   // has a marker reference loop.
   113   if (mInUse)
   114     return NS_OK;
   116   AutoMarkerReferencer markerRef(this, aMarkedFrame);
   118   SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(mContent);
   119   if (!marker->HasValidDimensions()) {
   120     return NS_OK;
   121   }
   123   const nsSVGViewBoxRect viewBox = marker->GetViewBoxRect();
   125   if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
   126     // We must disable rendering if the viewBox width or height are zero.
   127     return NS_OK;
   128   }
   130   mStrokeWidth = aStrokeWidth;
   131   mX = aMark->x;
   132   mY = aMark->y;
   133   mAutoAngle = aMark->angle;
   134   mIsStart = aMark->type == nsSVGMark::eStart;
   136   gfxContext *gfx = aContext->ThebesContext();
   138   if (StyleDisplay()->IsScrollableOverflow()) {
   139     gfx->Save();
   140     gfxRect clipRect =
   141       nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y,
   142                                       viewBox.width, viewBox.height);
   143     nsSVGUtils::SetClipRect(gfx, GetCanvasTM(nsISVGChildFrame::FOR_PAINTING),
   144                             clipRect);
   145   }
   147   nsIFrame* kid = GetAnonymousChildFrame(this);
   148   nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
   149   // The CTM of each frame referencing us may be different.
   150   SVGFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
   151   nsSVGUtils::PaintFrameWithEffects(aContext, nullptr, kid);
   153   if (StyleDisplay()->IsScrollableOverflow())
   154     gfx->Restore();
   156   return NS_OK;
   157 }
   159 SVGBBox
   160 nsSVGMarkerFrame::GetMarkBBoxContribution(const Matrix &aToBBoxUserspace,
   161                                           uint32_t aFlags,
   162                                           nsSVGPathGeometryFrame *aMarkedFrame,
   163                                           const nsSVGMark *aMark,
   164                                           float aStrokeWidth)
   165 {
   166   SVGBBox bbox;
   168   // If the flag is set when we get here, it means this marker frame
   169   // has already been used in calculating the current mark bbox, and
   170   // the document has a marker reference loop.
   171   if (mInUse)
   172     return bbox;
   174   AutoMarkerReferencer markerRef(this, aMarkedFrame);
   176   SVGMarkerElement *content = static_cast<SVGMarkerElement*>(mContent);
   177   if (!content->HasValidDimensions()) {
   178     return bbox;
   179   }
   181   const nsSVGViewBoxRect viewBox = content->GetViewBoxRect();
   183   if (viewBox.width <= 0.0f || viewBox.height <= 0.0f) {
   184     return bbox;
   185   }
   187   mStrokeWidth = aStrokeWidth;
   188   mX = aMark->x;
   189   mY = aMark->y;
   190   mAutoAngle = aMark->angle;
   191   mIsStart = aMark->type == nsSVGMark::eStart;
   193   Matrix markerTM =
   194     content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle, mIsStart);
   195   Matrix viewBoxTM = content->GetViewBoxTransform();
   197   Matrix tm = viewBoxTM * markerTM * aToBBoxUserspace;
   199   nsISVGChildFrame* child = do_QueryFrame(GetAnonymousChildFrame(this));
   200   // When we're being called to obtain the invalidation area, we need to
   201   // pass down all the flags so that stroke is included. However, once DOM
   202   // getBBox() accepts flags, maybe we should strip some of those here?
   204   // We need to include zero width/height vertical/horizontal lines, so we have
   205   // to use UnionEdges.
   206   bbox.UnionEdges(child->GetBBoxContribution(tm, aFlags));
   208   return bbox;
   209 }
   211 void
   212 nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext)
   213 {
   214   SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(mContent);
   215   marker->SetParentCoordCtxProvider(aContext);
   216 }
   218 //----------------------------------------------------------------------
   219 // helper class
   221 nsSVGMarkerFrame::AutoMarkerReferencer::AutoMarkerReferencer(
   222     nsSVGMarkerFrame *aFrame,
   223     nsSVGPathGeometryFrame *aMarkedFrame
   224     MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   225       : mFrame(aFrame)
   226 {
   227   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   228   mFrame->mInUse = true;
   229   mFrame->mMarkedFrame = aMarkedFrame;
   231   SVGSVGElement *ctx =
   232     static_cast<nsSVGElement*>(aMarkedFrame->GetContent())->GetCtx();
   233   mFrame->SetParentCoordCtxProvider(ctx);
   234 }
   236 nsSVGMarkerFrame::AutoMarkerReferencer::~AutoMarkerReferencer()
   237 {
   238   mFrame->SetParentCoordCtxProvider(nullptr);
   240   mFrame->mMarkedFrame = nullptr;
   241   mFrame->mInUse = false;
   242 }
   244 //----------------------------------------------------------------------
   245 // Implementation of nsSVGMarkerAnonChildFrame
   247 nsIFrame*
   248 NS_NewSVGMarkerAnonChildFrame(nsIPresShell* aPresShell,
   249                               nsStyleContext* aContext)
   250 {
   251   return new (aPresShell) nsSVGMarkerAnonChildFrame(aContext);
   252 }
   254 NS_IMPL_FRAMEARENA_HELPERS(nsSVGMarkerAnonChildFrame)
   256 #ifdef DEBUG
   257 void
   258 nsSVGMarkerAnonChildFrame::Init(nsIContent* aContent,
   259                                 nsIFrame* aParent,
   260                                 nsIFrame* aPrevInFlow)
   261 {
   262   NS_ABORT_IF_FALSE(aParent->GetType() == nsGkAtoms::svgMarkerFrame,
   263                     "Unexpected parent");
   264   nsSVGMarkerAnonChildFrameBase::Init(aContent, aParent, aPrevInFlow);
   265 }
   266 #endif
   268 nsIAtom *
   269 nsSVGMarkerAnonChildFrame::GetType() const
   270 {
   271   return nsGkAtoms::svgMarkerAnonChildFrame;
   272 }

mercurial