LCOV - app.info - content/svg/content/src/SVGLength.cpp

LCOV - code coverage report
| Current view: | directory - content/svg/content/src - SVGLength.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 87 | 0 | 0.0 %
| Date: | 2012-06-02 | Functions: | 9 | 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                 : #include "mozilla/Util.h"
          38                 :
          39                 : #include "SVGLength.h"
          40                 : #include "nsSVGElement.h"
          41                 : #include "nsSVGSVGElement.h"
          42                 : #include "nsString.h"
          43                 : #include "nsSVGUtils.h"
          44                 : #include "nsTextFormatter.h"
          45                 : #include "prdtoa.h"
          46                 : #include "nsMathUtils.h"
          47                 : #include <limits>
          48                 :
          49                 : namespace mozilla {
          50                 :
          51                 : // Declare some helpers defined below:
          52                 : static void GetUnitString(nsAString& unit, PRUint16 unitType);
          53                 : static PRUint16 GetUnitTypeForString(const char* unitStr);
          54                 :
          55                 : void
          56               0 : SVGLength::GetValueAsString(nsAString &aValue) const
          57                 : {
          58                 :   PRUnichar buf[24];
          59                 :   nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
          60               0 :                             NS_LITERAL_STRING("%g").get(),
          61               0 :                             (double)mValue);
          62               0 :   aValue.Assign(buf);
          63                 :
          64               0 :   nsAutoString unitString;
          65               0 :   GetUnitString(unitString, mUnit);
          66               0 :   aValue.Append(unitString);
          67               0 : }
          68                 :
          69                 : bool
          70               0 : SVGLength::SetValueFromString(const nsAString &aValue)
          71                 : {
          72                 :   float tmpValue;
          73                 :   PRUint16 tmpUnit;
          74                 :
          75               0 :   NS_ConvertUTF16toUTF8 value(aValue);
          76               0 :   const char *str = value.get();
          77                 :
          78               0 :   while (*str != '\0' && IsSVGWhitespace(*str)) {
          79               0 :     ++str;
          80                 :   }
          81                 :   char *unit;
          82               0 :   tmpValue = float(PR_strtod(str, &unit));
          83               0 :   if (unit != str && NS_finite(tmpValue)) {
          84               0 :     char *theRest = unit;
          85               0 :     if (*unit != '\0' && !IsSVGWhitespace(*unit)) {
          86               0 :       while (*theRest != '\0' && !IsSVGWhitespace(*theRest)) {
          87               0 :         ++theRest;
          88                 :       }
          89               0 :       nsCAutoString unitStr(unit, theRest - unit);
          90               0 :       tmpUnit = GetUnitTypeForString(unitStr.get());
          91               0 :       if (tmpUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN) {
          92                 :         // nsSVGUtils::ReportToConsole
          93               0 :         return false;
          94                 :       }
          95                 :     } else {
          96               0 :       tmpUnit = nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER;
          97                 :     }
          98               0 :     while (*theRest && IsSVGWhitespace(*theRest)) {
          99               0 :       ++theRest;
         100                 :     }
         101               0 :     if (!*theRest) {
         102               0 :       mValue = tmpValue;
         103               0 :       mUnit = tmpUnit;
         104               0 :       return true;
         105                 :     }
         106                 :   }
         107               0 :   return false;
         108                 : }
         109                 :
         110                 : inline static bool
         111               0 : IsAbsoluteUnit(PRUint8 aUnit)
         112                 : {
         113                 :   return aUnit >= nsIDOMSVGLength::SVG_LENGTHTYPE_CM &&
         114               0 :          aUnit <= nsIDOMSVGLength::SVG_LENGTHTYPE_PC;
         115                 : }
         116                 :
         117                 : /**
         118                 :  * Helper to convert between different CSS absolute units without the need for
         119                 :  * an element, which provides more flexibility at the DOM level (and without
         120                 :  * the need for an intermediary conversion to user units, which avoids
         121                 :  * unnecessary overhead and rounding error).
         122                 :  *
         123                 :  * Example usage: to find out how many centimeters there are per inch:
         124                 :  *
         125                 :  *   GetAbsUnitsPerAbsUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_CM,
         126                 :  *                         nsIDOMSVGLength::SVG_LENGTHTYPE_IN)
         127                 :  */
         128               0 : inline static float GetAbsUnitsPerAbsUnit(PRUint8 aUnits, PRUint8 aPerUnit)
         129                 : {
         130               0 :   NS_ABORT_IF_FALSE(IsAbsoluteUnit(aUnits), "Not a CSS absolute unit");
         131               0 :   NS_ABORT_IF_FALSE(IsAbsoluteUnit(aPerUnit), "Not a CSS absolute unit");
         132                 :
         133                 :   float CSSAbsoluteUnitConversionFactors[5][5] = { // columns: cm, mm, in, pt, pc
         134                 :     // cm per...:
         135                 :     { 1.0, 0.1, 2.54, 0.035277777777777778, 0.42333333333333333 },
         136                 :     // mm per...:
         137                 :     { 10.0, 1.0, 25.4, 0.35277777777777778, 4.2333333333333333 },
         138                 :     // in per...:
         139                 :     { 0.39370078740157481, 0.039370078740157481, 1.0, 0.013888888888888889, 0.16666666666666667 },
         140                 :     // pt per...:
         141                 :     { 28.346456692913386, 2.8346456692913386, 72.0, 1.0, 12.0 },
         142                 :     // pc per...:
         143                 :     { 2.3622047244094489, 0.23622047244094489, 6.0, 0.083333333333333333, 1.0 }
         144               0 :   };
         145                 :
         146                 :   // First absolute unit is SVG_LENGTHTYPE_CM = 6
         147               0 :   return CSSAbsoluteUnitConversionFactors[aUnits - 6][aPerUnit - 6];
         148                 : }
         149                 :
         150                 : float
         151               0 : SVGLength::GetValueInSpecifiedUnit(PRUint8 aUnit,
         152                 :                                    const nsSVGElement *aElement,
         153                 :                                    PRUint8 aAxis) const
         154                 : {
         155               0 :   if (aUnit == mUnit) {
         156               0 :     return mValue;
         157                 :   }
         158               0 :   if ((aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER &&
         159                 :        mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX) ||
         160                 :       (aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX &&
         161                 :        mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)) {
         162               0 :     return mValue;
         163                 :   }
         164               0 :   if (IsAbsoluteUnit(aUnit) && IsAbsoluteUnit(mUnit)) {
         165               0 :     return mValue * GetAbsUnitsPerAbsUnit(aUnit, mUnit);
         166                 :   }
         167                 :
         168                 :   // Otherwise we do a two step convertion via user units. This can only
         169                 :   // succeed if aElement is non-null (although that's not sufficent to
         170                 :   // guarantee success).
         171                 :
         172               0 :   float userUnitsPerCurrentUnit = GetUserUnitsPerUnit(aElement, aAxis);
         173                 :   float userUnitsPerNewUnit =
         174               0 :     SVGLength(0.0f, aUnit).GetUserUnitsPerUnit(aElement, aAxis);
         175                 :
         176               0 :   NS_ASSERTION(userUnitsPerCurrentUnit >= 0 ||
         177                 :                !NS_finite(userUnitsPerCurrentUnit),
         178                 :                "bad userUnitsPerCurrentUnit");
         179               0 :   NS_ASSERTION(userUnitsPerNewUnit >= 0 ||
         180                 :                !NS_finite(userUnitsPerNewUnit),
         181                 :                "bad userUnitsPerNewUnit");
         182                 :
         183               0 :   float value = mValue * userUnitsPerCurrentUnit / userUnitsPerNewUnit;
         184                 :
         185                 :   // userUnitsPerCurrentUnit could be infinity, or userUnitsPerNewUnit could
         186                 :   // be zero.
         187               0 :   if (NS_finite(value)) {
         188               0 :     return value;
         189                 :   }
         190               0 :   return std::numeric_limits<float>::quiet_NaN();
         191                 : }
         192                 :
         193                 : #define INCHES_PER_MM_FLOAT float(0.0393700787)
         194                 : #define INCHES_PER_CM_FLOAT float(0.393700787)
         195                 :
         196                 : float
         197               0 : SVGLength::GetUserUnitsPerUnit(const nsSVGElement *aElement, PRUint8 aAxis) const
         198                 : {
         199               0 :   switch (mUnit) {
         200                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER:
         201                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PX:
         202               0 :       return 1.0f;
         203                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_MM:
         204               0 :       return INCHES_PER_MM_FLOAT * GetUserUnitsPerInch();
         205                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_CM:
         206               0 :       return INCHES_PER_CM_FLOAT * GetUserUnitsPerInch();
         207                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_IN:
         208               0 :       return GetUserUnitsPerInch();
         209                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PT:
         210               0 :       return (1.0f/POINTS_PER_INCH_FLOAT) * GetUserUnitsPerInch();
         211                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PC:
         212               0 :       return (12.0f/POINTS_PER_INCH_FLOAT) * GetUserUnitsPerInch();
         213                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE:
         214               0 :       return GetUserUnitsPerPercent(aElement, aAxis);
         215                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS:
         216               0 :       return nsSVGUtils::GetFontSize(const_cast<nsSVGElement*>(aElement));
         217                 :     case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS:
         218               0 :       return nsSVGUtils::GetFontXHeight(const_cast<nsSVGElement*>(aElement));
         219                 :     default:
         220               0 :       NS_NOTREACHED("Unknown unit type");
         221               0 :       return std::numeric_limits<float>::quiet_NaN();
         222                 :   }
         223                 : }
         224                 :
         225                 : /* static */ float
         226               0 : SVGLength::GetUserUnitsPerPercent(const nsSVGElement *aElement, PRUint8 aAxis)
         227                 : {
         228               0 :   if (aElement) {
         229               0 :     nsSVGSVGElement *viewportElement = const_cast<nsSVGElement*>(aElement)->GetCtx();
         230               0 :     if (viewportElement) {
         231               0 :       return NS_MAX(viewportElement->GetLength(aAxis) / 100.0f, 0.0f);
         232                 :     }
         233                 :   }
         234               0 :   return std::numeric_limits<float>::quiet_NaN();
         235                 : }
         236                 :
         237                 : // Helpers:
         238                 :
         239                 : // These items must be at the same index as the nsIDOMSVGLength constants!
         240                 : static nsIAtom** const unitMap[] =
         241                 : {
         242                 :   nsnull, /* SVG_LENGTHTYPE_UNKNOWN */
         243                 :   nsnull, /* SVG_LENGTHTYPE_NUMBER */
         244                 :   &nsGkAtoms::percentage,
         245                 :   &nsGkAtoms::em,
         246                 :   &nsGkAtoms::ex,
         247                 :   &nsGkAtoms::px,
         248                 :   &nsGkAtoms::cm,
         249                 :   &nsGkAtoms::mm,
         250                 :   &nsGkAtoms::in,
         251                 :   &nsGkAtoms::pt,
         252                 :   &nsGkAtoms::pc
         253                 : };
         254                 :
         255                 : static void
         256               0 : GetUnitString(nsAString& unit, PRUint16 unitType)
         257                 : {
         258               0 :   if (SVGLength::IsValidUnitType(unitType)) {
         259               0 :     if (unitMap[unitType]) {
         260               0 :       (*unitMap[unitType])->ToString(unit);
         261                 :     }
         262               0 :     return;
         263                 :   }
         264               0 :   NS_NOTREACHED("Unknown unit type"); // Someone's using an SVGLength with an invalid unit?
         265               0 :   return;
         266                 : }
         267                 :
         268                 : static PRUint16
         269               0 : GetUnitTypeForString(const char* unitStr)
         270                 : {
         271               0 :   if (!unitStr || *unitStr == '\0')
         272               0 :     return nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER;
         273                 :
         274               0 :   nsCOMPtr<nsIAtom> unitAtom = do_GetAtom(unitStr);
         275                 :
         276               0 :   for (PRUint32 i = 1 ; i < ArrayLength(unitMap) ; i++) {
         277               0 :     if (unitMap[i] && *unitMap[i] == unitAtom) {
         278               0 :       return i;
         279                 :     }
         280                 :   }
         281               0 :   return nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN;
         282                 : }
         283                 :
         284                 : } // namespace mozilla

Generated by: LCOV version 1.7