LCOV - app.info - layout/svg/base/src/nsSVGPathGeometryFrame.cpp

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