LCOV - code coverage report
Current view: top level - dom/svg - SVGPathSegUtils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 49 36.7 %
Date: 2017-07-14 16:53:18 Functions: 5 15 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef MOZILLA_SVGPATHSEGUTILS_H__
       8             : #define MOZILLA_SVGPATHSEGUTILS_H__
       9             : 
      10             : #include "mozilla/ArrayUtils.h"
      11             : #include "mozilla/gfx/Point.h"
      12             : #include "nsDebug.h"
      13             : 
      14             : namespace mozilla {
      15             : 
      16             : // Path Segment Types
      17             : static const unsigned short PATHSEG_UNKNOWN                      = 0;
      18             : static const unsigned short PATHSEG_CLOSEPATH                    = 1;
      19             : static const unsigned short PATHSEG_MOVETO_ABS                   = 2;
      20             : static const unsigned short PATHSEG_MOVETO_REL                   = 3;
      21             : static const unsigned short PATHSEG_LINETO_ABS                   = 4;
      22             : static const unsigned short PATHSEG_LINETO_REL                   = 5;
      23             : static const unsigned short PATHSEG_CURVETO_CUBIC_ABS            = 6;
      24             : static const unsigned short PATHSEG_CURVETO_CUBIC_REL            = 7;
      25             : static const unsigned short PATHSEG_CURVETO_QUADRATIC_ABS        = 8;
      26             : static const unsigned short PATHSEG_CURVETO_QUADRATIC_REL        = 9;
      27             : static const unsigned short PATHSEG_ARC_ABS                      = 10;
      28             : static const unsigned short PATHSEG_ARC_REL                      = 11;
      29             : static const unsigned short PATHSEG_LINETO_HORIZONTAL_ABS        = 12;
      30             : static const unsigned short PATHSEG_LINETO_HORIZONTAL_REL        = 13;
      31             : static const unsigned short PATHSEG_LINETO_VERTICAL_ABS          = 14;
      32             : static const unsigned short PATHSEG_LINETO_VERTICAL_REL          = 15;
      33             : static const unsigned short PATHSEG_CURVETO_CUBIC_SMOOTH_ABS     = 16;
      34             : static const unsigned short PATHSEG_CURVETO_CUBIC_SMOOTH_REL     = 17;
      35             : static const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
      36             : static const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
      37             : 
      38             : #define NS_SVG_PATH_SEG_MAX_ARGS         7
      39             : #define NS_SVG_PATH_SEG_FIRST_VALID_TYPE mozilla::PATHSEG_CLOSEPATH
      40             : #define NS_SVG_PATH_SEG_LAST_VALID_TYPE  mozilla::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
      41             : #define NS_SVG_PATH_SEG_TYPE_COUNT       (NS_SVG_PATH_SEG_LAST_VALID_TYPE + 1)
      42             : 
      43             : /**
      44             :  * Code that works with path segments can use an instance of this class to
      45             :  * store/provide information about the start of the current subpath and the
      46             :  * last path segment (if any).
      47             :  */
      48             : struct SVGPathTraversalState
      49             : {
      50             :   typedef gfx::Point Point;
      51             : 
      52             :   enum TraversalMode {
      53             :     eUpdateAll,
      54             :     eUpdateOnlyStartAndCurrentPos
      55             :   };
      56             : 
      57           0 :   SVGPathTraversalState()
      58           0 :     : start(0.0, 0.0)
      59             :     , pos(0.0, 0.0)
      60             :     , cp1(0.0, 0.0)
      61             :     , cp2(0.0, 0.0)
      62             :     , length(0.0)
      63           0 :     , mode(eUpdateAll)
      64           0 :   {}
      65             : 
      66           0 :   bool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; }
      67             : 
      68             :   Point start; // start point of current sub path (reset each moveto)
      69             : 
      70             :   Point pos;   // current position (end point of previous segment)
      71             : 
      72             :   Point cp1;   // quadratic control point - if the previous segment was a
      73             :                // quadratic bezier curve then this is set to the absolute
      74             :                // position of its control point, otherwise its set to pos
      75             : 
      76             :   Point cp2;   // cubic control point - if the previous segment was a cubic
      77             :                // bezier curve then this is set to the absolute position of
      78             :                // its second control point, otherwise it's set to pos
      79             : 
      80             :   float length;   // accumulated path length
      81             : 
      82             :   TraversalMode mode;  // indicates what to track while traversing a path
      83             : };
      84             : 
      85             : 
      86             : /**
      87             :  * This class is just a collection of static methods - it doesn't have any data
      88             :  * members, and it's not possible to create instances of this class. This class
      89             :  * exists purely as a convenient place to gather together a bunch of methods
      90             :  * related to manipulating and answering questions about path segments.
      91             :  * Internally we represent path segments purely as an array of floats. See the
      92             :  * comment documenting SVGPathData for more info on that.
      93             :  *
      94             :  * The DOM wrapper classes for encoded path segments (data contained in
      95             :  * instances of SVGPathData) is DOMSVGPathSeg and its sub-classes. Note that
      96             :  * there are multiple different DOM classes for path segs - one for each of the
      97             :  * 19 SVG 1.1 segment types.
      98             :  */
      99             : class SVGPathSegUtils
     100             : {
     101             : private:
     102             :   SVGPathSegUtils(){} // private to prevent instances
     103             : 
     104             : public:
     105             : 
     106             :   static void GetValueAsString(const float *aSeg, nsAString& aValue);
     107             : 
     108             :   /**
     109             :    * Encode a segment type enum to a float.
     110             :    *
     111             :    * At some point in the future we will likely want to encode other
     112             :    * information into the float, such as whether the command was explicit or
     113             :    * not. For now all this method does is save on int to float runtime
     114             :    * conversion by requiring uint32_t and float to be of the same size so we
     115             :    * can simply do a bitwise uint32_t<->float copy.
     116             :    */
     117         894 :   static float EncodeType(uint32_t aType) {
     118             :     static_assert(sizeof(uint32_t) == sizeof(float), "sizeof uint32_t and float must be the same");
     119         894 :     MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
     120         894 :     return *(reinterpret_cast<float*>(&aType));
     121             :   }
     122             : 
     123         782 :   static uint32_t DecodeType(float aType) {
     124             :     static_assert(sizeof(uint32_t) == sizeof(float), "sizeof uint32_t and float must be the same");
     125         782 :     uint32_t type = *(reinterpret_cast<uint32_t*>(&aType));
     126         782 :     MOZ_ASSERT(IsValidType(type), "Seg type not recognized");
     127         782 :     return type;
     128             :   }
     129             : 
     130           0 :   static char16_t GetPathSegTypeAsLetter(uint32_t aType) {
     131           0 :     MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
     132             : 
     133             :     static const char16_t table[] = {
     134             :       char16_t('x'),  //  0 == PATHSEG_UNKNOWN
     135             :       char16_t('z'),  //  1 == PATHSEG_CLOSEPATH
     136             :       char16_t('M'),  //  2 == PATHSEG_MOVETO_ABS
     137             :       char16_t('m'),  //  3 == PATHSEG_MOVETO_REL
     138             :       char16_t('L'),  //  4 == PATHSEG_LINETO_ABS
     139             :       char16_t('l'),  //  5 == PATHSEG_LINETO_REL
     140             :       char16_t('C'),  //  6 == PATHSEG_CURVETO_CUBIC_ABS
     141             :       char16_t('c'),  //  7 == PATHSEG_CURVETO_CUBIC_REL
     142             :       char16_t('Q'),  //  8 == PATHSEG_CURVETO_QUADRATIC_ABS
     143             :       char16_t('q'),  //  9 == PATHSEG_CURVETO_QUADRATIC_REL
     144             :       char16_t('A'),  // 10 == PATHSEG_ARC_ABS
     145             :       char16_t('a'),  // 11 == PATHSEG_ARC_REL
     146             :       char16_t('H'),  // 12 == PATHSEG_LINETO_HORIZONTAL_ABS
     147             :       char16_t('h'),  // 13 == PATHSEG_LINETO_HORIZONTAL_REL
     148             :       char16_t('V'),  // 14 == PATHSEG_LINETO_VERTICAL_ABS
     149             :       char16_t('v'),  // 15 == PATHSEG_LINETO_VERTICAL_REL
     150             :       char16_t('S'),  // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
     151             :       char16_t('s'),  // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
     152             :       char16_t('T'),  // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
     153             :       char16_t('t')   // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
     154             :     };
     155             :     static_assert(MOZ_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT, "Unexpected table size");
     156             : 
     157           0 :     return table[aType];
     158             :   }
     159             : 
     160        1648 :   static uint32_t ArgCountForType(uint32_t aType) {
     161        1648 :     MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
     162             : 
     163             :     static const uint8_t table[] = {
     164             :       0,  //  0 == PATHSEG_UNKNOWN
     165             :       0,  //  1 == PATHSEG_CLOSEPATH
     166             :       2,  //  2 == PATHSEG_MOVETO_ABS
     167             :       2,  //  3 == PATHSEG_MOVETO_REL
     168             :       2,  //  4 == PATHSEG_LINETO_ABS
     169             :       2,  //  5 == PATHSEG_LINETO_REL
     170             :       6,  //  6 == PATHSEG_CURVETO_CUBIC_ABS
     171             :       6,  //  7 == PATHSEG_CURVETO_CUBIC_REL
     172             :       4,  //  8 == PATHSEG_CURVETO_QUADRATIC_ABS
     173             :       4,  //  9 == PATHSEG_CURVETO_QUADRATIC_REL
     174             :       7,  // 10 == PATHSEG_ARC_ABS
     175             :       7,  // 11 == PATHSEG_ARC_REL
     176             :       1,  // 12 == PATHSEG_LINETO_HORIZONTAL_ABS
     177             :       1,  // 13 == PATHSEG_LINETO_HORIZONTAL_REL
     178             :       1,  // 14 == PATHSEG_LINETO_VERTICAL_ABS
     179             :       1,  // 15 == PATHSEG_LINETO_VERTICAL_REL
     180             :       4,  // 16 == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
     181             :       4,  // 17 == PATHSEG_CURVETO_CUBIC_SMOOTH_REL
     182             :       2,  // 18 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
     183             :       2   // 19 == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
     184             :     };
     185             :     static_assert(MOZ_ARRAY_LENGTH(table) == NS_SVG_PATH_SEG_TYPE_COUNT, "Unexpected table size");
     186             : 
     187        1648 :     return table[aType];
     188             :   }
     189             : 
     190             :   /**
     191             :    * Convenience so that callers can pass a float containing an encoded type
     192             :    * and have it decoded implicitly.
     193             :    */
     194           0 :   static uint32_t ArgCountForType(float aType) {
     195           0 :     return ArgCountForType(DecodeType(aType));
     196             :   }
     197             : 
     198        3324 :   static bool IsValidType(uint32_t aType) {
     199        3324 :     return aType >= NS_SVG_PATH_SEG_FIRST_VALID_TYPE &&
     200        3324 :            aType <= NS_SVG_PATH_SEG_LAST_VALID_TYPE;
     201             :   }
     202             : 
     203          29 :   static bool IsCubicType(uint32_t aType) {
     204          10 :     return aType == PATHSEG_CURVETO_CUBIC_REL ||
     205           8 :            aType == PATHSEG_CURVETO_CUBIC_ABS ||
     206          33 :            aType == PATHSEG_CURVETO_CUBIC_SMOOTH_REL ||
     207          29 :            aType == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
     208             :   }
     209             : 
     210           0 :   static bool IsQuadraticType(uint32_t aType) {
     211           0 :     return aType == PATHSEG_CURVETO_QUADRATIC_REL ||
     212           0 :            aType == PATHSEG_CURVETO_QUADRATIC_ABS ||
     213           0 :            aType == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL ||
     214           0 :            aType == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
     215             :   }
     216             : 
     217           0 :   static bool IsArcType(uint32_t aType) {
     218           0 :     return aType == PATHSEG_ARC_ABS ||
     219           0 :            aType == PATHSEG_ARC_REL;
     220             :   }
     221             : 
     222           0 :   static bool IsRelativeOrAbsoluteType(uint32_t aType) {
     223           0 :     MOZ_ASSERT(IsValidType(aType), "Seg type not recognized");
     224             : 
     225             :     // When adding a new path segment type, ensure that the returned condition
     226             :     // below is still correct.
     227             :     static_assert(NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
     228             :                   "Unexpected type");
     229             : 
     230           0 :     return aType >= PATHSEG_MOVETO_ABS;
     231             :   }
     232             : 
     233           0 :   static bool IsRelativeType(uint32_t aType) {
     234           0 :     MOZ_ASSERT
     235             :       (IsRelativeOrAbsoluteType(aType),
     236             :        "IsRelativeType called with segment type that does not come in relative and absolute forms");
     237             : 
     238             :     // When adding a new path segment type, ensure that the returned condition
     239             :     // below is still correct.
     240             :     static_assert(NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
     241             :                   "Unexpected type");
     242             : 
     243           0 :     return aType & 1;
     244             :   }
     245             : 
     246           0 :   static uint32_t RelativeVersionOfType(uint32_t aType) {
     247           0 :     MOZ_ASSERT
     248             :       (IsRelativeOrAbsoluteType(aType),
     249             :        "RelativeVersionOfType called with segment type that does not come in relative and absolute forms");
     250             : 
     251             :     // When adding a new path segment type, ensure that the returned condition
     252             :     // below is still correct.
     253             :     static_assert(NS_SVG_PATH_SEG_LAST_VALID_TYPE == PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
     254             :                   "Unexpected type");
     255             : 
     256           0 :     return aType | 1;
     257             :   }
     258             : 
     259           0 :   static uint32_t SameTypeModuloRelativeness(uint32_t aType1, uint32_t aType2) {
     260           0 :     if (!IsRelativeOrAbsoluteType(aType1)) {
     261           0 :       return aType1 == aType2;
     262             :     }
     263             : 
     264           0 :     return RelativeVersionOfType(aType1) == RelativeVersionOfType(aType2);
     265             :   }
     266             : 
     267             :   /**
     268             :    * Traverse the given path segment and update the SVGPathTraversalState
     269             :    * object.
     270             :    */
     271             :   static void TraversePathSegment(const float* aData,
     272             :                                   SVGPathTraversalState& aState);
     273             : };
     274             : 
     275             : } // namespace mozilla
     276             : 
     277             : #endif // MOZILLA_SVGPATHSEGUTILS_H__

Generated by: LCOV version 1.13