LCOV - code coverage report
Current view: directory - content/svg/content/src - SVGPathData.h (source / functions) Found Hit Coverage
Test: app.info Lines: 37 0 0.0 %
Date: 2012-06-02 Functions: 17 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 Mozilla SVG Project code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is the Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      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 the GNU General Public License Version 2 or later (the "GPL"), or
      25                 :  * 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                 : #ifndef MOZILLA_SVGPATHDATA_H__
      38                 : #define MOZILLA_SVGPATHDATA_H__
      39                 : 
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsDebug.h"
      42                 : #include "nsIContent.h"
      43                 : #include "nsINode.h"
      44                 : #include "nsIWeakReferenceUtils.h"
      45                 : #include "nsSVGElement.h"
      46                 : #include "nsTArray.h"
      47                 : 
      48                 : #include <string.h>
      49                 : 
      50                 : class gfxContext;
      51                 : class gfxFlattenedPath;
      52                 : class nsSVGPathDataParserToInternal; // IWYU pragma: keep
      53                 : 
      54                 : struct gfxMatrix;
      55                 : struct nsSVGMark;
      56                 : 
      57                 : namespace mozilla {
      58                 : 
      59                 : /**
      60                 :  * ATTENTION! WARNING! WATCH OUT!!
      61                 :  *
      62                 :  * Consumers that modify objects of this type absolutely MUST keep the DOM
      63                 :  * wrappers for those lists (if any) in sync!! That's why this class is so
      64                 :  * locked down.
      65                 :  *
      66                 :  * The DOM wrapper class for this class is DOMSVGPathSegList.
      67                 :  *
      68                 :  * This class is not called |class SVGPathSegList| for one very good reason;
      69                 :  * this class does not provide a list of "SVGPathSeg" items, it provides an
      70                 :  * array of floats into which path segments are encoded. See the paragraphs
      71                 :  * that follow for why. Note that the Length() method returns the number of
      72                 :  * floats in our array, not the number of encoded segments, and the index
      73                 :  * operator indexes floats in the array, not segments. If this class were
      74                 :  * called SVGPathSegList the names of these methods would be very misleading.
      75                 :  *
      76                 :  * The reason this class is designed in this way is because there are many
      77                 :  * different types of path segment, each taking a different numbers of
      78                 :  * arguments. We want to store the segments in an nsTArray to avoid individual
      79                 :  * allocations for each item, but the different size of segments means we can't
      80                 :  * have one single segment type for the nsTArray (not without using a space
      81                 :  * wasteful union or something similar). Since the internal code does not need
      82                 :  * to index into the list (the DOM wrapper does, but it handles that itself)
      83                 :  * the obvious solution is to have the items in this class take up variable
      84                 :  * width and have the internal code iterate over these lists rather than index
      85                 :  * into them.
      86                 :  *
      87                 :  * Implementing indexing to segments with O(1) performance would require us to
      88                 :  * allocate and maintain a separate segment index table (keeping that table in
      89                 :  * sync when items are inserted or removed from the list). So long as the
      90                 :  * internal code doesn't require indexing to segments, we can avoid that
      91                 :  * overhead and additional complexity.
      92                 :  *
      93                 :  * Segment encoding: the first float in the encoding of a segment contains the
      94                 :  * segment's type. The segment's type is encoded to/decoded from this float
      95                 :  * using the static methods SVGPathSegUtils::EncodeType(PRUint32)/
      96                 :  * SVGPathSegUtils::DecodeType(float). If the path segment type in question
      97                 :  * takes any arguments then these follow the first float, and are in the same
      98                 :  * order as they are given in a <path> element's 'd' attribute (NOT in the
      99                 :  * order of the createSVGPathSegXxx() methods' arguments from the SVG DOM
     100                 :  * interface SVGPathElement, which are different...grr). Consumers can use
     101                 :  * SVGPathSegUtils::ArgCountForType(type) to determine how many arguments
     102                 :  * there are (if any), and thus where the current encoded segment ends, and
     103                 :  * where the next segment (if any) begins.
     104                 :  */
     105                 : class SVGPathData
     106                 : {
     107                 :   friend class SVGAnimatedPathSegList;
     108                 :   friend class DOMSVGPathSegList;
     109                 :   friend class DOMSVGPathSeg;
     110                 :   friend class ::nsSVGPathDataParserToInternal;
     111                 :   // nsSVGPathDataParserToInternal will not keep wrappers in sync, so consumers
     112                 :   // are responsible for that!
     113                 : 
     114                 : public:
     115                 :   typedef const float* const_iterator;
     116                 : 
     117               0 :   SVGPathData(){}
     118               0 :   ~SVGPathData(){}
     119                 : 
     120                 :   // Only methods that don't make/permit modification to this list are public.
     121                 :   // Only our friend classes can access methods that may change us.
     122                 : 
     123                 :   /// This may return an incomplete string on OOM, but that's acceptable.
     124                 :   void GetValueAsString(nsAString& aValue) const;
     125                 : 
     126               0 :   bool IsEmpty() const {
     127               0 :     return mData.IsEmpty();
     128                 :   }
     129                 : 
     130                 : #ifdef DEBUG
     131                 :   /**
     132                 :    * This method iterates over the encoded segment data and counts the number
     133                 :    * of segments we currently have.
     134                 :    */
     135                 :   PRUint32 CountItems() const;
     136                 : #endif
     137                 : 
     138                 :   /**
     139                 :    * Returns the number of *floats* in the encoding array, and NOT the number
     140                 :    * of segments encoded in this object. (For that, see CountItems() above.)
     141                 :    */
     142               0 :   PRUint32 Length() const {
     143               0 :     return mData.Length();
     144                 :   }
     145                 : 
     146                 :   const float& operator[](PRUint32 aIndex) const {
     147                 :     return mData[aIndex];
     148                 :   }
     149                 : 
     150                 :   // Used by nsSMILCompositor to check if the cached base val is out of date
     151               0 :   bool operator==(const SVGPathData& rhs) const {
     152                 :     // We use memcmp so that we don't need to worry that the data encoded in
     153                 :     // the first float may have the same bit pattern as a NaN.
     154               0 :     return mData.Length() == rhs.mData.Length() &&
     155               0 :            memcmp(mData.Elements(), rhs.mData.Elements(),
     156               0 :                   mData.Length() * sizeof(float)) == 0;
     157                 :   }
     158                 : 
     159                 :   bool SetCapacity(PRUint32 aSize) {
     160                 :     return mData.SetCapacity(aSize);
     161                 :   }
     162                 : 
     163                 :   void Compact() {
     164                 :     mData.Compact();
     165                 :   }
     166                 : 
     167                 : 
     168                 :   float GetPathLength() const;
     169                 : 
     170                 :   PRUint32 GetPathSegAtLength(float aLength) const;
     171                 : 
     172                 :   void GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const;
     173                 : 
     174                 :   /**
     175                 :    * Returns true, except on OOM, in which case returns false.
     176                 :    */
     177                 :   bool GetSegmentLengths(nsTArray<double> *aLengths) const;
     178                 : 
     179                 :   /**
     180                 :    * Returns true, except on OOM, in which case returns false.
     181                 :    */
     182                 :   bool GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aArray) const;
     183                 : 
     184                 :   already_AddRefed<gfxFlattenedPath>
     185                 :   ToFlattenedPath(const gfxMatrix& aMatrix) const;
     186                 : 
     187                 :   void ConstructPath(gfxContext *aCtx) const;
     188                 : 
     189               0 :   const_iterator begin() const { return mData.Elements(); }
     190               0 :   const_iterator end() const { return mData.Elements() + mData.Length(); }
     191                 : 
     192                 :   // Access to methods that can modify objects of this type is deliberately
     193                 :   // limited. This is to reduce the chances of someone modifying objects of
     194                 :   // this type without taking the necessary steps to keep DOM wrappers in sync.
     195                 :   // If you need wider access to these methods, consider adding a method to
     196                 :   // SVGAnimatedPathSegList and having that class act as an intermediary so it
     197                 :   // can take care of keeping DOM wrappers in sync.
     198                 : 
     199                 : protected:
     200                 :   typedef float* iterator;
     201                 : 
     202                 :   /**
     203                 :    * This may fail on OOM if the internal capacity needs to be increased, in
     204                 :    * which case the list will be left unmodified.
     205                 :    */
     206                 :   nsresult CopyFrom(const SVGPathData& rhs);
     207                 : 
     208                 :   float& operator[](PRUint32 aIndex) {
     209                 :     return mData[aIndex];
     210                 :   }
     211                 : 
     212                 :   /**
     213                 :    * This may fail (return false) on OOM if the internal capacity is being
     214                 :    * increased, in which case the list will be left unmodified.
     215                 :    */
     216               0 :   bool SetLength(PRUint32 aLength) {
     217               0 :     return mData.SetLength(aLength);
     218                 :   }
     219                 : 
     220                 :   nsresult SetValueFromString(const nsAString& aValue);
     221                 : 
     222               0 :   void Clear() {
     223               0 :     mData.Clear();
     224               0 :   }
     225                 : 
     226                 :   // Our DOM wrappers have direct access to our mData, so they directly
     227                 :   // manipulate it rather than us implementing:
     228                 :   //
     229                 :   // * InsertItem(PRUint32 aDataIndex, PRUint32 aType, const float *aArgs);
     230                 :   // * ReplaceItem(PRUint32 aDataIndex, PRUint32 aType, const float *aArgs);
     231                 :   // * RemoveItem(PRUint32 aDataIndex);
     232                 :   // * bool AppendItem(PRUint32 aType, const float *aArgs);
     233                 : 
     234                 :   nsresult AppendSeg(PRUint32 aType, ...); // variable number of float args
     235                 : 
     236               0 :   iterator begin() { return mData.Elements(); }
     237               0 :   iterator end() { return mData.Elements() + mData.Length(); }
     238                 : 
     239                 :   nsTArray<float> mData;
     240                 : };
     241                 : 
     242                 : 
     243                 : /**
     244                 :  * This SVGPathData subclass is for SVGPathSegListSMILType which needs to
     245                 :  * have write access to the lists it works with.
     246                 :  *
     247                 :  * Instances of this class do not have DOM wrappers that need to be kept in
     248                 :  * sync, so we can safely expose any protected base class methods required by
     249                 :  * the SMIL code.
     250                 :  */
     251                 : class SVGPathDataAndOwner : public SVGPathData
     252               0 : {
     253                 : public:
     254               0 :   SVGPathDataAndOwner(nsSVGElement *aElement = nsnull)
     255               0 :     : mElement(do_GetWeakReference(static_cast<nsINode*>(aElement)))
     256               0 :   {}
     257                 : 
     258               0 :   void SetElement(nsSVGElement *aElement) {
     259               0 :     mElement = do_GetWeakReference(static_cast<nsINode*>(aElement));
     260               0 :   }
     261                 : 
     262               0 :   nsSVGElement* Element() const {
     263               0 :     nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
     264               0 :     return static_cast<nsSVGElement*>(e.get());
     265                 :   }
     266                 : 
     267               0 :   nsresult CopyFrom(const SVGPathDataAndOwner& rhs) {
     268               0 :     mElement = rhs.mElement;
     269               0 :     return SVGPathData::CopyFrom(rhs);
     270                 :   }
     271                 : 
     272               0 :   bool IsIdentity() const {
     273               0 :     if (!mElement) {
     274               0 :       NS_ABORT_IF_FALSE(IsEmpty(), "target element propagation failure");
     275               0 :       return true;
     276                 :     }
     277               0 :     return false;
     278                 :   }
     279                 : 
     280                 :   /**
     281                 :    * Exposed so that SVGPathData baseVals can be copied to
     282                 :    * SVGPathDataAndOwner objects. Note that callers should also call
     283                 :    * SetElement() when using this method!
     284                 :    */
     285                 :   using SVGPathData::CopyFrom;
     286                 : 
     287                 :   // Exposed since SVGPathData objects can be modified.
     288                 :   using SVGPathData::iterator;
     289                 :   using SVGPathData::operator[];
     290                 :   using SVGPathData::SetLength;
     291                 :   using SVGPathData::begin;
     292                 :   using SVGPathData::end;
     293                 : 
     294                 : private:
     295                 :   // We must keep a weak reference to our element because we may belong to a
     296                 :   // cached baseVal nsSMILValue. See the comments starting at:
     297                 :   // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
     298                 :   // See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
     299                 :   nsWeakPtr mElement;
     300                 : };
     301                 : 
     302                 : } // namespace mozilla
     303                 : 
     304                 : #endif // MOZILLA_SVGPATHDATA_H__

Generated by: LCOV version 1.7