LCOV - code coverage report
Current view: directory - layout/svg/base/src - nsSVGPathGeometryFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 200 0 0.0 %
Date: 2012-06-02 Functions: 23 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Crocodile Clips Ltd..
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsSVGPathGeometryFrame.h"
      40                 : #include "nsGkAtoms.h"
      41                 : #include "nsSVGMarkerFrame.h"
      42                 : #include "nsSVGUtils.h"
      43                 : #include "nsSVGEffects.h"
      44                 : #include "nsSVGGraphicElement.h"
      45                 : #include "nsSVGOuterSVGFrame.h"
      46                 : #include "nsSVGRect.h"
      47                 : #include "nsSVGPathGeometryElement.h"
      48                 : #include "gfxContext.h"
      49                 : #include "gfxPlatform.h"
      50                 : 
      51                 : //----------------------------------------------------------------------
      52                 : // Implementation
      53                 : 
      54                 : nsIFrame*
      55               0 : NS_NewSVGPathGeometryFrame(nsIPresShell* aPresShell,
      56                 :                            nsStyleContext* aContext)
      57                 : {
      58               0 :   return new (aPresShell) nsSVGPathGeometryFrame(aContext);
      59                 : }
      60                 : 
      61               0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGPathGeometryFrame)
      62                 : 
      63                 : //----------------------------------------------------------------------
      64                 : // nsQueryFrame methods
      65                 : 
      66               0 : NS_QUERYFRAME_HEAD(nsSVGPathGeometryFrame)
      67               0 :   NS_QUERYFRAME_ENTRY(nsISVGChildFrame)
      68               0 : NS_QUERYFRAME_TAIL_INHERITING(nsSVGPathGeometryFrameBase)
      69                 : 
      70                 : //----------------------------------------------------------------------
      71                 : // nsIFrame methods
      72                 : 
      73                 : NS_IMETHODIMP
      74               0 : nsSVGPathGeometryFrame::AttributeChanged(PRInt32         aNameSpaceID,
      75                 :                                          nsIAtom*        aAttribute,
      76                 :                                          PRInt32         aModType)
      77                 : {
      78               0 :   if (aNameSpaceID == kNameSpaceID_None &&
      79                 :       (static_cast<nsSVGPathGeometryElement*>
      80               0 :                   (mContent)->AttributeDefinesGeometry(aAttribute) ||
      81                 :        aAttribute == nsGkAtoms::transform))
      82               0 :     nsSVGUtils::UpdateGraphic(this);
      83                 : 
      84               0 :   return NS_OK;
      85                 : }
      86                 : 
      87                 : /* virtual */ void
      88               0 : nsSVGPathGeometryFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
      89                 : {
      90               0 :   nsSVGPathGeometryFrameBase::DidSetStyleContext(aOldStyleContext);
      91                 : 
      92                 :   // XXX: we'd like to use the style_hint mechanism and the
      93                 :   // ContentStateChanged/AttributeChanged functions for style changes
      94                 :   // to get slightly finer granularity, but unfortunately the
      95                 :   // style_hints don't map very well onto svg. Here seems to be the
      96                 :   // best place to deal with style changes:
      97                 : 
      98               0 :   nsSVGUtils::UpdateGraphic(this);
      99               0 : }
     100                 : 
     101                 : nsIAtom *
     102               0 : nsSVGPathGeometryFrame::GetType() const
     103                 : {
     104               0 :   return nsGkAtoms::svgPathGeometryFrame;
     105                 : }
     106                 : 
     107                 : //----------------------------------------------------------------------
     108                 : // nsISVGChildFrame methods
     109                 : 
     110                 : NS_IMETHODIMP
     111               0 : nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
     112                 :                                  const nsIntRect *aDirtyRect)
     113                 : {
     114               0 :   if (!GetStyleVisibility()->IsVisible())
     115               0 :     return NS_OK;
     116                 : 
     117                 :   /* render */
     118               0 :   Render(aContext);
     119                 : 
     120               0 :   if (static_cast<nsSVGPathGeometryElement*>(mContent)->IsMarkable()) {
     121               0 :     MarkerProperties properties = GetMarkerProperties(this);
     122                 :       
     123               0 :     if (properties.MarkersExist()) {
     124               0 :       float strokeWidth = GetStrokeWidth();
     125                 :         
     126               0 :       nsTArray<nsSVGMark> marks;
     127                 :       static_cast<nsSVGPathGeometryElement*>
     128               0 :                  (mContent)->GetMarkPoints(&marks);
     129                 :         
     130               0 :       PRUint32 num = marks.Length();
     131                 : 
     132               0 :       if (num) {
     133               0 :         nsSVGMarkerFrame *frame = properties.GetMarkerStartFrame();
     134               0 :         if (frame)
     135               0 :           frame->PaintMark(aContext, this, &marks[0], strokeWidth);
     136                 : 
     137               0 :         frame = properties.GetMarkerMidFrame();
     138               0 :         if (frame) {
     139               0 :           for (PRUint32 i = 1; i < num - 1; i++)
     140               0 :             frame->PaintMark(aContext, this, &marks[i], strokeWidth);
     141                 :         }
     142                 : 
     143               0 :         frame = properties.GetMarkerEndFrame();
     144               0 :         if (frame)
     145               0 :           frame->PaintMark(aContext, this, &marks[num-1], strokeWidth);
     146                 :       }
     147                 :     }
     148                 :   }
     149                 : 
     150               0 :   return NS_OK;
     151                 : }
     152                 : 
     153                 : NS_IMETHODIMP_(nsIFrame*)
     154               0 : nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
     155                 : {
     156                 :   PRUint16 fillRule, hitTestFlags;
     157               0 :   if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
     158               0 :     hitTestFlags = SVG_HIT_TEST_FILL;
     159               0 :     fillRule = GetClipRule();
     160                 :   } else {
     161               0 :     hitTestFlags = GetHitTestFlags();
     162                 :     // XXX once bug 614732 is fixed, aPoint won't need any conversion in order
     163                 :     // to compare it with mRect.
     164               0 :     gfxMatrix canvasTM = GetCanvasTM();
     165               0 :     if (canvasTM.IsSingular()) {
     166               0 :       return nsnull;
     167                 :     }
     168                 :     nsPoint point =
     169               0 :       nsSVGUtils::TransformOuterSVGPointToChildFrame(aPoint, canvasTM, PresContext());
     170               0 :     if (!hitTestFlags || ((hitTestFlags & SVG_HIT_TEST_CHECK_MRECT) &&
     171               0 :                           !mRect.Contains(point)))
     172               0 :       return nsnull;
     173               0 :     fillRule = GetStyleSVG()->mFillRule;
     174                 :   }
     175                 : 
     176               0 :   bool isHit = false;
     177                 : 
     178                 :   nsRefPtr<gfxContext> context =
     179               0 :     new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
     180                 : 
     181               0 :   GeneratePath(context);
     182                 :   gfxPoint userSpacePoint =
     183                 :     context->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
     184               0 :                                    PresContext()->AppUnitsToGfxUnits(aPoint.y)));
     185                 : 
     186               0 :   if (fillRule == NS_STYLE_FILL_RULE_EVENODD)
     187               0 :     context->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
     188                 :   else
     189               0 :     context->SetFillRule(gfxContext::FILL_RULE_WINDING);
     190                 : 
     191               0 :   if (hitTestFlags & SVG_HIT_TEST_FILL)
     192               0 :     isHit = context->PointInFill(userSpacePoint);
     193               0 :   if (!isHit && (hitTestFlags & SVG_HIT_TEST_STROKE)) {
     194               0 :     SetupCairoStrokeHitGeometry(context);
     195               0 :     isHit = context->PointInStroke(userSpacePoint);
     196                 :   }
     197                 : 
     198               0 :   if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
     199               0 :     return this;
     200                 : 
     201               0 :   return nsnull;
     202                 : }
     203                 : 
     204                 : NS_IMETHODIMP_(nsRect)
     205               0 : nsSVGPathGeometryFrame::GetCoveredRegion()
     206                 : {
     207                 :   // See bug 614732 comment 32:
     208                 :   //return nsSVGUtils::TransformFrameRectToOuterSVG(mRect, GetCanvasTM(), PresContext());
     209               0 :   return mCoveredRegion;
     210                 : }
     211                 : 
     212                 : NS_IMETHODIMP
     213               0 : nsSVGPathGeometryFrame::UpdateCoveredRegion()
     214                 : {
     215                 :   gfxRect extent = GetBBoxContribution(gfxMatrix(),
     216                 :     nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIgnoreFillIfNone |
     217                 :     nsSVGUtils::eBBoxIncludeStroke | nsSVGUtils::eBBoxIgnoreStrokeIfNone |
     218               0 :     nsSVGUtils::eBBoxIncludeMarkers);
     219                 :   mRect = nsLayoutUtils::RoundGfxRectToAppRect(extent,
     220               0 :             PresContext()->AppUnitsPerCSSPixel());
     221                 : 
     222                 :   // See bug 614732 comment 32.
     223                 :   mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG(
     224               0 :     mRect, GetCanvasTM(), PresContext());
     225                 : 
     226               0 :   return NS_OK;
     227                 : }
     228                 : 
     229                 : NS_IMETHODIMP
     230               0 : nsSVGPathGeometryFrame::InitialUpdate()
     231                 : {
     232               0 :   NS_ASSERTION(GetStateBits() & NS_FRAME_FIRST_REFLOW,
     233                 :                "Yikes! We've been called already! Hopefully we weren't called "
     234                 :                "before our nsSVGOuterSVGFrame's initial Reflow()!!!");
     235                 : 
     236               0 :   nsSVGUtils::UpdateGraphic(this);
     237                 : 
     238               0 :   NS_ASSERTION(!(mState & NS_FRAME_IN_REFLOW),
     239                 :                "We don't actually participate in reflow");
     240                 :   
     241                 :   // Do unset the various reflow bits, though.
     242                 :   mState &= ~(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY |
     243               0 :               NS_FRAME_HAS_DIRTY_CHILDREN);
     244               0 :   return NS_OK;
     245                 : }
     246                 : 
     247                 : void
     248               0 : nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags)
     249                 : {
     250               0 :   NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) ||
     251                 :                     (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD),
     252                 :                     "Must be NS_STATE_SVG_NONDISPLAY_CHILD!");
     253                 : 
     254               0 :   NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED),
     255                 :                     "Invalidation logic may need adjusting");
     256                 : 
     257               0 :   if (!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS)) {
     258               0 :     nsSVGUtils::UpdateGraphic(this);
     259                 :   }
     260               0 : }
     261                 : 
     262                 : void
     263               0 : nsSVGPathGeometryFrame::NotifyRedrawSuspended()
     264                 : {
     265               0 :   AddStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
     266               0 : }
     267                 : 
     268                 : void
     269               0 : nsSVGPathGeometryFrame::NotifyRedrawUnsuspended()
     270                 : {
     271               0 :   RemoveStateBits(NS_STATE_SVG_REDRAW_SUSPENDED);
     272                 : 
     273               0 :   if (GetStateBits() & NS_STATE_SVG_DIRTY)
     274               0 :     nsSVGUtils::UpdateGraphic(this);
     275               0 : }
     276                 : 
     277                 : gfxRect
     278               0 : nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
     279                 :                                             PRUint32 aFlags)
     280                 : {
     281               0 :   if (aToBBoxUserspace.IsSingular()) {
     282                 :     // XXX ReportToConsole
     283               0 :     return gfxRect(0.0, 0.0, 0.0, 0.0);
     284                 :   }
     285                 : 
     286                 :   nsRefPtr<gfxContext> context =
     287               0 :     new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
     288                 : 
     289               0 :   GeneratePath(context, &aToBBoxUserspace);
     290               0 :   context->IdentityMatrix();
     291                 : 
     292               0 :   gfxRect bbox;
     293                 : 
     294                 :   // Be careful when replacing the following logic to get the fill and stroke
     295                 :   // extents independently (instead of computing the stroke extents from the
     296                 :   // path extents). You may think that you can just use the stroke extents if
     297                 :   // there is both a fill and a stroke. In reality it's necessary to calculate
     298                 :   // both the fill and stroke extents, and take the union of the two. There are
     299                 :   // two reasons for this:
     300                 :   //
     301                 :   // # Due to stroke dashing, in certain cases the fill extents could actually
     302                 :   //   extend outside the stroke extents.
     303                 :   // # If the stroke is very thin, cairo won't paint any stroke, and so the
     304                 :   //   stroke bounds that it will return will be empty.
     305                 : 
     306               0 :   gfxRect pathExtents = context->GetUserPathExtent();
     307                 : 
     308                 :   // Account for fill:
     309               0 :   if ((aFlags & nsSVGUtils::eBBoxIncludeFill) != 0 &&
     310                 :       ((aFlags & nsSVGUtils::eBBoxIgnoreFillIfNone) == 0 ||
     311               0 :        GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)) {
     312               0 :     bbox = pathExtents;
     313                 :   }
     314                 : 
     315                 :   // Account for stroke:
     316               0 :   if ((aFlags & nsSVGUtils::eBBoxIncludeStroke) != 0 &&
     317               0 :       ((aFlags & nsSVGUtils::eBBoxIgnoreStrokeIfNone) == 0 || HasStroke())) {
     318                 :     // We can't use context->GetUserStrokeExtent() since it doesn't work for
     319                 :     // device space extents. Instead we approximate the stroke extents from
     320                 :     // pathExtents using PathExtentsToMaxStrokeExtents.
     321               0 :     if (pathExtents.Width() <= 0 && pathExtents.Height() <= 0) {
     322                 :       // We have a zero length path, but it may still have non-empty stroke
     323                 :       // bounds depending on the value of stroke-linecap. We need to fix up
     324                 :       // pathExtents before it can be used with PathExtentsToMaxStrokeExtents
     325                 :       // though, because if pathExtents is empty, its position will not have
     326                 :       // been set. Happily we can use context->GetUserStrokeExtent() to find
     327                 :       // the center point of the extents even though it gets the extents wrong.
     328               0 :       SetupCairoStrokeGeometry(context);
     329               0 :       pathExtents.MoveTo(context->GetUserStrokeExtent().Center());
     330               0 :       pathExtents.SizeTo(0, 0);
     331                 :     }
     332                 :     bbox =
     333                 :       bbox.Union(nsSVGUtils::PathExtentsToMaxStrokeExtents(pathExtents,
     334                 :                                                            this,
     335               0 :                                                            aToBBoxUserspace));
     336                 :   }
     337                 : 
     338                 :   // Account for markers:
     339               0 :   if ((aFlags & nsSVGUtils::eBBoxIncludeMarkers) != 0 &&
     340               0 :       static_cast<nsSVGPathGeometryElement*>(mContent)->IsMarkable()) {
     341                 : 
     342               0 :     float strokeWidth = GetStrokeWidth();
     343               0 :     MarkerProperties properties = GetMarkerProperties(this);
     344                 : 
     345               0 :     if (properties.MarkersExist()) {
     346               0 :       nsTArray<nsSVGMark> marks;
     347               0 :       static_cast<nsSVGPathGeometryElement*>(mContent)->GetMarkPoints(&marks);
     348               0 :       PRUint32 num = marks.Length();
     349                 : 
     350               0 :       if (num) {
     351               0 :         nsSVGMarkerFrame *frame = properties.GetMarkerStartFrame();
     352               0 :         if (frame) {
     353                 :           gfxRect mbbox =
     354                 :             frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
     355               0 :                                            &marks[0], strokeWidth);
     356               0 :           bbox.UnionRect(bbox, mbbox);
     357                 :         }
     358                 : 
     359               0 :         frame = properties.GetMarkerMidFrame();
     360               0 :         if (frame) {
     361               0 :           for (PRUint32 i = 1; i < num - 1; i++) {
     362                 :             gfxRect mbbox =
     363                 :               frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
     364               0 :                                              &marks[i], strokeWidth);
     365               0 :             bbox.UnionRect(bbox, mbbox);
     366                 :           }
     367                 :         }
     368                 : 
     369               0 :         frame = properties.GetMarkerEndFrame();
     370               0 :         if (frame) {
     371                 :           gfxRect mbbox =
     372                 :             frame->GetMarkBBoxContribution(aToBBoxUserspace, aFlags, this,
     373               0 :                                            &marks[num-1], strokeWidth);
     374               0 :           bbox.UnionRect(bbox, mbbox);
     375                 :         }
     376                 :       }
     377                 :     }
     378                 :   }
     379                 : 
     380               0 :   return bbox;
     381                 : }
     382                 : 
     383                 : //----------------------------------------------------------------------
     384                 : // nsSVGGeometryFrame methods:
     385                 : 
     386                 : gfxMatrix
     387               0 : nsSVGPathGeometryFrame::GetCanvasTM()
     388                 : {
     389               0 :   NS_ASSERTION(mParent, "null parent");
     390                 : 
     391               0 :   nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
     392               0 :   nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent);
     393                 : 
     394               0 :   return content->PrependLocalTransformsTo(parent->GetCanvasTM());
     395                 : }
     396                 : 
     397                 : //----------------------------------------------------------------------
     398                 : // nsSVGPathGeometryFrame methods:
     399                 : 
     400                 : nsSVGPathGeometryFrame::MarkerProperties
     401               0 : nsSVGPathGeometryFrame::GetMarkerProperties(nsSVGPathGeometryFrame *aFrame)
     402                 : {
     403               0 :   NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame should be first continuation");
     404                 : 
     405                 :   MarkerProperties result;
     406               0 :   const nsStyleSVG *style = aFrame->GetStyleSVG();
     407                 :   result.mMarkerStart =
     408                 :     nsSVGEffects::GetMarkerProperty(style->mMarkerStart, aFrame,
     409               0 :                                     nsSVGEffects::MarkerBeginProperty());
     410                 :   result.mMarkerMid =
     411                 :     nsSVGEffects::GetMarkerProperty(style->mMarkerMid, aFrame,
     412               0 :                                     nsSVGEffects::MarkerMiddleProperty());
     413                 :   result.mMarkerEnd =
     414                 :     nsSVGEffects::GetMarkerProperty(style->mMarkerEnd, aFrame,
     415               0 :                                     nsSVGEffects::MarkerEndProperty());
     416                 :   return result;
     417                 : }
     418                 : 
     419                 : nsSVGMarkerFrame *
     420               0 : nsSVGPathGeometryFrame::MarkerProperties::GetMarkerStartFrame()
     421                 : {
     422               0 :   if (!mMarkerStart)
     423               0 :     return nsnull;
     424                 :   return static_cast<nsSVGMarkerFrame *>
     425               0 :     (mMarkerStart->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nsnull));
     426                 : }
     427                 : 
     428                 : nsSVGMarkerFrame *
     429               0 : nsSVGPathGeometryFrame::MarkerProperties::GetMarkerMidFrame()
     430                 : {
     431               0 :   if (!mMarkerMid)
     432               0 :     return nsnull;
     433                 :   return static_cast<nsSVGMarkerFrame *>
     434               0 :     (mMarkerMid->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nsnull));
     435                 : }
     436                 : 
     437                 : nsSVGMarkerFrame *
     438               0 : nsSVGPathGeometryFrame::MarkerProperties::GetMarkerEndFrame()
     439                 : {
     440               0 :   if (!mMarkerEnd)
     441               0 :     return nsnull;
     442                 :   return static_cast<nsSVGMarkerFrame *>
     443               0 :     (mMarkerEnd->GetReferencedFrame(nsGkAtoms::svgMarkerFrame, nsnull));
     444                 : }
     445                 : 
     446                 : void
     447               0 : nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext)
     448                 : {
     449               0 :   gfxContext *gfx = aContext->ThebesContext();
     450                 : 
     451               0 :   PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext);
     452                 : 
     453               0 :   switch (GetStyleSVG()->mShapeRendering) {
     454                 :   case NS_STYLE_SHAPE_RENDERING_OPTIMIZESPEED:
     455                 :   case NS_STYLE_SHAPE_RENDERING_CRISPEDGES:
     456               0 :     gfx->SetAntialiasMode(gfxContext::MODE_ALIASED);
     457               0 :     break;
     458                 :   default:
     459               0 :     gfx->SetAntialiasMode(gfxContext::MODE_COVERAGE);
     460               0 :     break;
     461                 :   }
     462                 : 
     463                 :   /* save/restore the state so we don't screw up the xform */
     464               0 :   gfx->Save();
     465                 : 
     466               0 :   GeneratePath(gfx);
     467                 : 
     468               0 :   if (renderMode != SVGAutoRenderState::NORMAL) {
     469               0 :     gfx->Restore();
     470                 : 
     471               0 :     if (GetClipRule() == NS_STYLE_FILL_RULE_EVENODD)
     472               0 :       gfx->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
     473                 :     else
     474               0 :       gfx->SetFillRule(gfxContext::FILL_RULE_WINDING);
     475                 : 
     476               0 :     if (renderMode == SVGAutoRenderState::CLIP_MASK) {
     477               0 :       gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
     478               0 :       gfx->Fill();
     479               0 :       gfx->NewPath();
     480                 :     }
     481                 : 
     482               0 :     return;
     483                 :   }
     484                 : 
     485               0 :   if (SetupCairoFill(gfx)) {
     486               0 :     gfx->Fill();
     487                 :   }
     488                 : 
     489               0 :   if (SetupCairoStroke(gfx)) {
     490               0 :     gfx->Stroke();
     491                 :   }
     492                 : 
     493               0 :   gfx->NewPath();
     494                 : 
     495               0 :   gfx->Restore();
     496                 : }
     497                 : 
     498                 : void
     499               0 : nsSVGPathGeometryFrame::GeneratePath(gfxContext* aContext,
     500                 :                                      const gfxMatrix *aOverrideTransform)
     501                 : {
     502               0 :   gfxMatrix matrix;
     503               0 :   if (aOverrideTransform) {
     504               0 :     matrix = *aOverrideTransform;
     505                 :   } else {
     506               0 :     matrix = GetCanvasTM();
     507                 :   }
     508                 : 
     509               0 :   if (matrix.IsSingular()) {
     510               0 :     aContext->IdentityMatrix();
     511               0 :     aContext->NewPath();
     512               0 :     return;
     513                 :   }
     514                 : 
     515               0 :   aContext->Multiply(matrix);
     516                 : 
     517                 :   // Hack to let SVGPathData::ConstructPath know if we have square caps:
     518               0 :   const nsStyleSVG* style = GetStyleSVG();
     519               0 :   if (style->mStrokeLinecap == NS_STYLE_STROKE_LINECAP_SQUARE) {
     520               0 :     aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
     521                 :   }
     522                 : 
     523               0 :   aContext->NewPath();
     524               0 :   static_cast<nsSVGPathGeometryElement*>(mContent)->ConstructPath(aContext);
     525                 : }

Generated by: LCOV version 1.7