LCOV - code coverage report
Current view: top level - dom/svg - SVGLength.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 81 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
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             : #include "mozilla/ArrayUtils.h"
       8             : 
       9             : #include "SVGLength.h"
      10             : #include "nsSVGElement.h"
      11             : #include "mozilla/dom/SVGSVGElement.h"
      12             : #include "nsTextFormatter.h"
      13             : #include "SVGContentUtils.h"
      14             : #include <limits>
      15             : #include <algorithm>
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : // Declare some helpers defined below:
      20             : static void GetUnitString(nsAString& unit, uint16_t unitType);
      21             : static uint16_t GetUnitTypeForString(const nsAString& unitStr);
      22             : 
      23             : void
      24           0 : SVGLength::GetValueAsString(nsAString &aValue) const
      25             : {
      26             :   char16_t buf[24];
      27           0 :   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
      28             :                             u"%g",
      29           0 :                             (double)mValue);
      30           0 :   aValue.Assign(buf);
      31             : 
      32           0 :   nsAutoString unitString;
      33           0 :   GetUnitString(unitString, mUnit);
      34           0 :   aValue.Append(unitString);
      35           0 : }
      36             : 
      37             : bool
      38           0 : SVGLength::SetValueFromString(const nsAString &aString)
      39             : {
      40             :   RangedPtr<const char16_t> iter =
      41           0 :     SVGContentUtils::GetStartRangedPtr(aString);
      42             :   const RangedPtr<const char16_t> end =
      43           0 :     SVGContentUtils::GetEndRangedPtr(aString);
      44             : 
      45             :   float value;
      46             : 
      47           0 :   if (!SVGContentUtils::ParseNumber(iter, end, value)) {
      48           0 :     return false;
      49             :   }
      50             : 
      51           0 :   const nsAString& units = Substring(iter.get(), end.get());
      52           0 :   uint16_t unitType = GetUnitTypeForString(units);
      53           0 :   if (!IsValidUnitType(unitType)) {
      54           0 :     return false;
      55             :   }
      56           0 :   mValue = value;
      57           0 :   mUnit = uint8_t(unitType);
      58           0 :   return true;
      59             : }
      60             : 
      61             : inline static bool
      62           0 : IsAbsoluteUnit(uint8_t aUnit)
      63             : {
      64           0 :   return aUnit >= nsIDOMSVGLength::SVG_LENGTHTYPE_CM &&
      65           0 :          aUnit <= nsIDOMSVGLength::SVG_LENGTHTYPE_PC;
      66             : }
      67             : 
      68             : /**
      69             :  * Helper to convert between different CSS absolute units without the need for
      70             :  * an element, which provides more flexibility at the DOM level (and without
      71             :  * the need for an intermediary conversion to user units, which avoids
      72             :  * unnecessary overhead and rounding error).
      73             :  *
      74             :  * Example usage: to find out how many centimeters there are per inch:
      75             :  *
      76             :  *   GetAbsUnitsPerAbsUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_CM,
      77             :  *                         nsIDOMSVGLength::SVG_LENGTHTYPE_IN)
      78             :  */
      79           0 : inline static float GetAbsUnitsPerAbsUnit(uint8_t aUnits, uint8_t aPerUnit)
      80             : {
      81           0 :   MOZ_ASSERT(IsAbsoluteUnit(aUnits), "Not a CSS absolute unit");
      82           0 :   MOZ_ASSERT(IsAbsoluteUnit(aPerUnit), "Not a CSS absolute unit");
      83             : 
      84             :   float CSSAbsoluteUnitConversionFactors[5][5] = { // columns: cm, mm, in, pt, pc
      85             :     // cm per...:
      86             :     { 1.0f, 0.1f, 2.54f, 0.035277777777777778f, 0.42333333333333333f },
      87             :     // mm per...:
      88             :     { 10.0f, 1.0f, 25.4f, 0.35277777777777778f, 4.2333333333333333f },
      89             :     // in per...:
      90             :     { 0.39370078740157481f, 0.039370078740157481f, 1.0f, 0.013888888888888889f, 0.16666666666666667f },
      91             :     // pt per...:
      92             :     { 28.346456692913386f, 2.8346456692913386f, 72.0f, 1.0f, 12.0f },
      93             :     // pc per...:
      94             :     { 2.3622047244094489f, 0.23622047244094489f, 6.0f, 0.083333333333333333f, 1.0f }
      95           0 :   };
      96             : 
      97             :   // First absolute unit is SVG_LENGTHTYPE_CM = 6
      98           0 :   return CSSAbsoluteUnitConversionFactors[aUnits - 6][aPerUnit - 6];
      99             : }
     100             : 
     101             : float
     102           0 : SVGLength::GetValueInSpecifiedUnit(uint8_t aUnit,
     103             :                                    const nsSVGElement *aElement,
     104             :                                    uint8_t aAxis) const
     105             : {
     106           0 :   if (aUnit == mUnit) {
     107           0 :     return mValue;
     108             :   }
     109           0 :   if ((aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER &&
     110           0 :        mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX) ||
     111           0 :       (aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX &&
     112           0 :        mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)) {
     113           0 :     return mValue;
     114             :   }
     115           0 :   if (IsAbsoluteUnit(aUnit) && IsAbsoluteUnit(mUnit)) {
     116           0 :     return mValue * GetAbsUnitsPerAbsUnit(aUnit, mUnit);
     117             :   }
     118             : 
     119             :   // Otherwise we do a two step convertion via user units. This can only
     120             :   // succeed if aElement is non-null (although that's not sufficent to
     121             :   // guarantee success).
     122             : 
     123           0 :   float userUnitsPerCurrentUnit = GetUserUnitsPerUnit(aElement, aAxis);
     124             :   float userUnitsPerNewUnit =
     125           0 :     SVGLength(0.0f, aUnit).GetUserUnitsPerUnit(aElement, aAxis);
     126             : 
     127           0 :   NS_ASSERTION(userUnitsPerCurrentUnit >= 0 ||
     128             :                !IsFinite(userUnitsPerCurrentUnit),
     129             :                "bad userUnitsPerCurrentUnit");
     130           0 :   NS_ASSERTION(userUnitsPerNewUnit >= 0 ||
     131             :                !IsFinite(userUnitsPerNewUnit),
     132             :                "bad userUnitsPerNewUnit");
     133             : 
     134           0 :   float value = mValue * userUnitsPerCurrentUnit / userUnitsPerNewUnit;
     135             : 
     136             :   // userUnitsPerCurrentUnit could be infinity, or userUnitsPerNewUnit could
     137             :   // be zero.
     138           0 :   if (IsFinite(value)) {
     139           0 :     return value;
     140             :   }
     141           0 :   return std::numeric_limits<float>::quiet_NaN();
     142             : }
     143             : 
     144             : #define INCHES_PER_MM_FLOAT float(0.0393700787)
     145             : #define INCHES_PER_CM_FLOAT float(0.393700787)
     146             : 
     147             : float
     148           0 : SVGLength::GetUserUnitsPerUnit(const nsSVGElement *aElement, uint8_t aAxis) const
     149             : {
     150           0 :   switch (mUnit) {
     151             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
     152             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
     153           0 :       return 1.0f;
     154             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_MM:
     155           0 :       return INCHES_PER_MM_FLOAT * GetUserUnitsPerInch();
     156             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_CM:
     157           0 :       return INCHES_PER_CM_FLOAT * GetUserUnitsPerInch();
     158             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_IN:
     159           0 :       return GetUserUnitsPerInch();
     160             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PT:
     161           0 :       return (1.0f/POINTS_PER_INCH_FLOAT) * GetUserUnitsPerInch();
     162             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
     163           0 :       return (12.0f/POINTS_PER_INCH_FLOAT) * GetUserUnitsPerInch();
     164             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
     165           0 :       return GetUserUnitsPerPercent(aElement, aAxis);
     166             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
     167           0 :       return SVGContentUtils::GetFontSize(const_cast<nsSVGElement*>(aElement));
     168             :     case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
     169           0 :       return SVGContentUtils::GetFontXHeight(const_cast<nsSVGElement*>(aElement));
     170             :     default:
     171           0 :       NS_NOTREACHED("Unknown unit type");
     172           0 :       return std::numeric_limits<float>::quiet_NaN();
     173             :   }
     174             : }
     175             : 
     176             : /* static */ float
     177           0 : SVGLength::GetUserUnitsPerPercent(const nsSVGElement *aElement, uint8_t aAxis)
     178             : {
     179           0 :   if (aElement) {
     180           0 :     dom::SVGSVGElement *viewportElement = aElement->GetCtx();
     181           0 :     if (viewportElement) {
     182           0 :       return std::max(viewportElement->GetLength(aAxis) / 100.0f, 0.0f);
     183             :     }
     184             :   }
     185           0 :   return std::numeric_limits<float>::quiet_NaN();
     186             : }
     187             : 
     188             : // Helpers:
     189             : 
     190             : // These items must be at the same index as the nsIDOMSVGLength constants!
     191             : static nsIAtom** const unitMap[] =
     192             : {
     193             :   nullptr, /* SVG_LENGTHTYPE_UNKNOWN */
     194             :   nullptr, /* SVG_LENGTHTYPE_NUMBER */
     195             :   &nsGkAtoms::percentage,
     196             :   &nsGkAtoms::em,
     197             :   &nsGkAtoms::ex,
     198             :   &nsGkAtoms::px,
     199             :   &nsGkAtoms::cm,
     200             :   &nsGkAtoms::mm,
     201             :   &nsGkAtoms::in,
     202             :   &nsGkAtoms::pt,
     203             :   &nsGkAtoms::pc
     204             : };
     205             : 
     206             : static void
     207           0 : GetUnitString(nsAString& unit, uint16_t unitType)
     208             : {
     209           0 :   if (SVGLength::IsValidUnitType(unitType)) {
     210           0 :     if (unitMap[unitType]) {
     211           0 :       (*unitMap[unitType])->ToString(unit);
     212             :     }
     213           0 :     return;
     214             :   }
     215           0 :   NS_NOTREACHED("Unknown unit type"); // Someone's using an SVGLength with an invalid unit?
     216           0 :   return;
     217             : }
     218             : 
     219             : static uint16_t
     220           0 : GetUnitTypeForString(const nsAString& unitStr)
     221             : {
     222           0 :   if (unitStr.IsEmpty())
     223           0 :     return nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER;
     224             : 
     225           0 :   nsIAtom* unitAtom = NS_GetStaticAtom(unitStr);
     226             : 
     227           0 :   if (unitAtom) {
     228           0 :     for (uint32_t i = 1 ; i < ArrayLength(unitMap) ; i++) {
     229           0 :       if (unitMap[i] && *unitMap[i] == unitAtom) {
     230           0 :         return i;
     231             :       }
     232             :     }
     233             :   }
     234           0 :   return nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN;
     235             : }
     236             : 
     237             : } // namespace mozilla

Generated by: LCOV version 1.13