LCOV - code coverage report
Current view: directory - layout/svg/base/src - nsSVGGeometryFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 152 0 0.0 %
Date: 2012-06-02 Functions: 16 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 IBM Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2006
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *
      23                 :  * Alternatively, the contents of this file may be used under the terms of
      24                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      25                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      27                 :  * of those above. If you wish to allow use of your version of this file only
      28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      29                 :  * use your version of this file under the terms of the MPL, indicate your
      30                 :  * decision by deleting the provisions above and replace them with the notice
      31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      32                 :  * the provisions above, a recipient may use your version of this file under
      33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      34                 :  *
      35                 :  * ***** END LICENSE BLOCK ***** */
      36                 : 
      37                 : #include "nsPresContext.h"
      38                 : #include "nsSVGPathElement.h"
      39                 : #include "nsSVGUtils.h"
      40                 : #include "nsSVGGeometryFrame.h"
      41                 : #include "nsSVGPaintServerFrame.h"
      42                 : #include "nsContentUtils.h"
      43                 : #include "gfxContext.h"
      44                 : #include "nsSVGEffects.h"
      45                 : 
      46               0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGGeometryFrame)
      47                 : 
      48                 : //----------------------------------------------------------------------
      49                 : // nsIFrame methods
      50                 : 
      51                 : NS_IMETHODIMP
      52               0 : nsSVGGeometryFrame::Init(nsIContent* aContent,
      53                 :                          nsIFrame* aParent,
      54                 :                          nsIFrame* aPrevInFlow)
      55                 : {
      56               0 :   AddStateBits(aParent->GetStateBits() &
      57                 :                (NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD |
      58               0 :                 NS_STATE_SVG_REDRAW_SUSPENDED));
      59               0 :   nsresult rv = nsSVGGeometryFrameBase::Init(aContent, aParent, aPrevInFlow);
      60               0 :   return rv;
      61                 : }
      62                 : 
      63                 : //----------------------------------------------------------------------
      64                 : 
      65                 : nsSVGPaintServerFrame *
      66               0 : nsSVGGeometryFrame::GetPaintServer(const nsStyleSVGPaint *aPaint,
      67                 :                                    const FramePropertyDescriptor *aType)
      68                 : {
      69               0 :   if (aPaint->mType != eStyleSVGPaintType_Server)
      70               0 :     return nsnull;
      71                 : 
      72               0 :   nsIFrame *frame = mContent->IsNodeOfType(nsINode::eTEXT) ?
      73               0 :                       GetParent() : this;
      74                 :   nsSVGPaintingProperty *property =
      75               0 :     nsSVGEffects::GetPaintingProperty(aPaint->mPaint.mPaintServer, frame, aType);
      76               0 :   if (!property)
      77               0 :     return nsnull;
      78               0 :   nsIFrame *result = property->GetReferencedFrame();
      79               0 :   if (!result)
      80               0 :     return nsnull;
      81                 : 
      82               0 :   nsIAtom *type = result->GetType();
      83               0 :   if (type != nsGkAtoms::svgLinearGradientFrame &&
      84                 :       type != nsGkAtoms::svgRadialGradientFrame &&
      85                 :       type != nsGkAtoms::svgPatternFrame)
      86               0 :     return nsnull;
      87                 : 
      88               0 :   return static_cast<nsSVGPaintServerFrame*>(result);
      89                 : }
      90                 : 
      91                 : float
      92               0 : nsSVGGeometryFrame::GetStrokeWidth()
      93                 : {
      94                 :   nsSVGElement *ctx = static_cast<nsSVGElement*>
      95               0 :                                  (mContent->IsNodeOfType(nsINode::eTEXT) ?
      96               0 :                                      mContent->GetParent() : mContent);
      97                 : 
      98                 :   return
      99                 :     nsSVGUtils::CoordToFloat(PresContext(),
     100                 :                              ctx,
     101               0 :                              GetStyleSVG()->mStrokeWidth);
     102                 : }
     103                 : 
     104                 : bool
     105               0 : nsSVGGeometryFrame::GetStrokeDashData(FallibleTArray<gfxFloat>& dashes,
     106                 :                                       gfxFloat *dashOffset)
     107                 : {
     108               0 :   PRUint32 count = GetStyleSVG()->mStrokeDasharrayLength;
     109               0 :   if (!count || !dashes.SetLength(count)) {
     110               0 :     return false;
     111                 :   }
     112                 : 
     113               0 :   gfxFloat pathScale = 1.0;
     114                 : 
     115               0 :   if (mContent->Tag() == nsGkAtoms::path) {
     116                 :     pathScale = static_cast<nsSVGPathElement*>(mContent)->
     117               0 :                   GetPathLengthScale(nsSVGPathElement::eForStroking);
     118               0 :     if (pathScale <= 0) {
     119               0 :       return false;
     120                 :     }
     121                 :   }
     122                 :   
     123                 :   nsSVGElement *ctx = static_cast<nsSVGElement*>
     124               0 :                                  (mContent->IsNodeOfType(nsINode::eTEXT) ?
     125               0 :                                      mContent->GetParent() : mContent);
     126                 : 
     127               0 :   const nsStyleCoord *dasharray = GetStyleSVG()->mStrokeDasharray;
     128               0 :   nsPresContext *presContext = PresContext();
     129               0 :   gfxFloat totalLength = 0.0;
     130                 : 
     131               0 :   for (PRUint32 i = 0; i < count; i++) {
     132               0 :     dashes[i] =
     133                 :       nsSVGUtils::CoordToFloat(presContext,
     134                 :                                ctx,
     135               0 :                                dasharray[i]) * pathScale;
     136               0 :     if (dashes[i] < 0.0) {
     137               0 :       return false;
     138                 :     }
     139               0 :     totalLength += dashes[i];
     140                 :   }
     141                 : 
     142                 :   *dashOffset = nsSVGUtils::CoordToFloat(presContext,
     143                 :                                          ctx,
     144               0 :                                          GetStyleSVG()->mStrokeDashoffset);
     145                 : 
     146               0 :   return (totalLength > 0.0);
     147                 : }
     148                 : 
     149                 : PRUint16
     150               0 : nsSVGGeometryFrame::GetClipRule()
     151                 : {
     152               0 :   return GetStyleSVG()->mClipRule;
     153                 : }
     154                 : 
     155                 : static void
     156               0 : SetupCairoColor(gfxContext *aContext, nscolor aRGB, float aOpacity)
     157                 : {
     158                 :   aContext->SetColor(gfxRGBA(NS_GET_R(aRGB)/255.0,
     159                 :                              NS_GET_G(aRGB)/255.0,
     160                 :                              NS_GET_B(aRGB)/255.0,
     161               0 :                              NS_GET_A(aRGB)/255.0 * aOpacity));
     162               0 : }
     163                 : 
     164                 : static void
     165               0 : SetupFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext,
     166                 :                           nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
     167                 :                           float aOpacity)
     168                 : {
     169                 :   nscolor color;
     170                 :   nsSVGUtils::GetFallbackOrPaintColor(aContext, aStyleContext, aFillOrStroke,
     171               0 :                                       &aOpacity, &color);
     172                 : 
     173               0 :   SetupCairoColor(aContext, color, aOpacity);
     174               0 : }
     175                 : 
     176                 : float
     177               0 : nsSVGGeometryFrame::MaybeOptimizeOpacity(float aFillOrStrokeOpacity)
     178                 : {
     179               0 :   float opacity = GetStyleDisplay()->mOpacity;
     180               0 :   if (opacity < 1 && nsSVGUtils::CanOptimizeOpacity(this)) {
     181               0 :     return aFillOrStrokeOpacity * opacity;
     182                 :   }
     183               0 :   return aFillOrStrokeOpacity;
     184                 : }
     185                 : 
     186                 : bool
     187               0 : nsSVGGeometryFrame::SetupCairoFill(gfxContext *aContext)
     188                 : {
     189               0 :   const nsStyleSVG* style = GetStyleSVG();
     190               0 :   if (style->mFill.mType == eStyleSVGPaintType_None)
     191               0 :     return false;
     192                 : 
     193               0 :   if (style->mFillRule == NS_STYLE_FILL_RULE_EVENODD)
     194               0 :     aContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
     195                 :   else
     196               0 :     aContext->SetFillRule(gfxContext::FILL_RULE_WINDING);
     197                 : 
     198               0 :   float opacity = MaybeOptimizeOpacity(style->mFillOpacity);
     199                 : 
     200                 :   nsSVGPaintServerFrame *ps =
     201               0 :     GetPaintServer(&style->mFill, nsSVGEffects::FillProperty());
     202               0 :   if (ps && ps->SetupPaintServer(aContext, this, opacity))
     203               0 :     return true;
     204                 : 
     205                 :   // On failure, use the fallback colour in case we have an
     206                 :   // objectBoundingBox where the width or height of the object is zero.
     207                 :   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
     208                 :   SetupFallbackOrPaintColor(aContext, GetStyleContext(),
     209               0 :                             &nsStyleSVG::mFill, opacity);
     210                 : 
     211               0 :   return true;
     212                 : }
     213                 : 
     214                 : bool
     215               0 : nsSVGGeometryFrame::HasStroke()
     216                 : {
     217               0 :   const nsStyleSVG *style = GetStyleSVG();
     218                 :   return style->mStroke.mType != eStyleSVGPaintType_None &&
     219                 :          style->mStrokeOpacity > 0 &&
     220               0 :          GetStrokeWidth() > 0;
     221                 : }
     222                 : 
     223                 : void
     224               0 : nsSVGGeometryFrame::SetupCairoStrokeGeometry(gfxContext *aContext)
     225                 : {
     226               0 :   float width = GetStrokeWidth();
     227               0 :   if (width <= 0)
     228               0 :     return;
     229               0 :   aContext->SetLineWidth(width);
     230                 : 
     231               0 :   const nsStyleSVG* style = GetStyleSVG();
     232                 :   
     233               0 :   switch (style->mStrokeLinecap) {
     234                 :   case NS_STYLE_STROKE_LINECAP_BUTT:
     235               0 :     aContext->SetLineCap(gfxContext::LINE_CAP_BUTT);
     236               0 :     break;
     237                 :   case NS_STYLE_STROKE_LINECAP_ROUND:
     238               0 :     aContext->SetLineCap(gfxContext::LINE_CAP_ROUND);
     239               0 :     break;
     240                 :   case NS_STYLE_STROKE_LINECAP_SQUARE:
     241               0 :     aContext->SetLineCap(gfxContext::LINE_CAP_SQUARE);
     242               0 :     break;
     243                 :   }
     244                 : 
     245               0 :   aContext->SetMiterLimit(style->mStrokeMiterlimit);
     246                 : 
     247               0 :   switch (style->mStrokeLinejoin) {
     248                 :   case NS_STYLE_STROKE_LINEJOIN_MITER:
     249               0 :     aContext->SetLineJoin(gfxContext::LINE_JOIN_MITER);
     250               0 :     break;
     251                 :   case NS_STYLE_STROKE_LINEJOIN_ROUND:
     252               0 :     aContext->SetLineJoin(gfxContext::LINE_JOIN_ROUND);
     253               0 :     break;
     254                 :   case NS_STYLE_STROKE_LINEJOIN_BEVEL:
     255               0 :     aContext->SetLineJoin(gfxContext::LINE_JOIN_BEVEL);
     256               0 :     break;
     257                 :   }
     258                 : }
     259                 : 
     260                 : void
     261               0 : nsSVGGeometryFrame::SetupCairoStrokeHitGeometry(gfxContext *aContext)
     262                 : {
     263               0 :   SetupCairoStrokeGeometry(aContext);
     264                 : 
     265               0 :   AutoFallibleTArray<gfxFloat, 10> dashes;
     266                 :   gfxFloat dashOffset;
     267               0 :   if (GetStrokeDashData(dashes, &dashOffset)) {
     268               0 :     aContext->SetDash(dashes.Elements(), dashes.Length(), dashOffset);
     269                 :   }
     270               0 : }
     271                 : 
     272                 : bool
     273               0 : nsSVGGeometryFrame::SetupCairoStroke(gfxContext *aContext)
     274                 : {
     275               0 :   if (!HasStroke()) {
     276               0 :     return false;
     277                 :   }
     278               0 :   SetupCairoStrokeHitGeometry(aContext);
     279                 : 
     280               0 :   const nsStyleSVG* style = GetStyleSVG();
     281               0 :   float opacity = MaybeOptimizeOpacity(style->mStrokeOpacity);
     282                 : 
     283                 :   nsSVGPaintServerFrame *ps =
     284               0 :     GetPaintServer(&style->mStroke, nsSVGEffects::StrokeProperty());
     285               0 :   if (ps && ps->SetupPaintServer(aContext, this, opacity))
     286               0 :     return true;
     287                 : 
     288                 :   // On failure, use the fallback colour in case we have an
     289                 :   // objectBoundingBox where the width or height of the object is zero.
     290                 :   // See http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
     291                 :   SetupFallbackOrPaintColor(aContext, GetStyleContext(),
     292               0 :                             &nsStyleSVG::mStroke, opacity);
     293                 : 
     294               0 :   return true;
     295                 : }
     296                 : 
     297                 : PRUint16
     298               0 : nsSVGGeometryFrame::GetHitTestFlags()
     299                 : {
     300               0 :   PRUint16 flags = 0;
     301                 : 
     302               0 :   switch(GetStyleVisibility()->mPointerEvents) {
     303                 :   case NS_STYLE_POINTER_EVENTS_NONE:
     304               0 :     break;
     305                 :   case NS_STYLE_POINTER_EVENTS_AUTO:
     306                 :   case NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED:
     307               0 :     if (GetStyleVisibility()->IsVisible()) {
     308               0 :       if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)
     309               0 :         flags |= SVG_HIT_TEST_FILL;
     310               0 :       if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None)
     311               0 :         flags |= SVG_HIT_TEST_STROKE;
     312               0 :       if (GetStyleSVG()->mStrokeOpacity > 0)
     313               0 :         flags |= SVG_HIT_TEST_CHECK_MRECT;
     314                 :     }
     315               0 :     break;
     316                 :   case NS_STYLE_POINTER_EVENTS_VISIBLEFILL:
     317               0 :     if (GetStyleVisibility()->IsVisible()) {
     318               0 :       flags |= SVG_HIT_TEST_FILL;
     319                 :     }
     320               0 :     break;
     321                 :   case NS_STYLE_POINTER_EVENTS_VISIBLESTROKE:
     322               0 :     if (GetStyleVisibility()->IsVisible()) {
     323               0 :       flags |= SVG_HIT_TEST_STROKE;
     324                 :     }
     325               0 :     break;
     326                 :   case NS_STYLE_POINTER_EVENTS_VISIBLE:
     327               0 :     if (GetStyleVisibility()->IsVisible()) {
     328               0 :       flags |= SVG_HIT_TEST_FILL | SVG_HIT_TEST_STROKE;
     329                 :     }
     330               0 :     break;
     331                 :   case NS_STYLE_POINTER_EVENTS_PAINTED:
     332               0 :     if (GetStyleSVG()->mFill.mType != eStyleSVGPaintType_None)
     333               0 :       flags |= SVG_HIT_TEST_FILL;
     334               0 :     if (GetStyleSVG()->mStroke.mType != eStyleSVGPaintType_None)
     335               0 :       flags |= SVG_HIT_TEST_STROKE;
     336               0 :     if (GetStyleSVG()->mStrokeOpacity)
     337               0 :       flags |= SVG_HIT_TEST_CHECK_MRECT;
     338               0 :     break;
     339                 :   case NS_STYLE_POINTER_EVENTS_FILL:
     340               0 :     flags |= SVG_HIT_TEST_FILL;
     341               0 :     break;
     342                 :   case NS_STYLE_POINTER_EVENTS_STROKE:
     343               0 :     flags |= SVG_HIT_TEST_STROKE;
     344               0 :     break;
     345                 :   case NS_STYLE_POINTER_EVENTS_ALL:
     346               0 :     flags |= SVG_HIT_TEST_FILL | SVG_HIT_TEST_STROKE;
     347               0 :     break;
     348                 :   default:
     349               0 :     NS_ERROR("not reached");
     350               0 :     break;
     351                 :   }
     352                 : 
     353               0 :   return flags;
     354                 : }

Generated by: LCOV version 1.7