LCOV - code coverage report
Current view: top level - layout/style - nsStyleUtil.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 61 395 15.4 %
Date: 2017-07-14 16:53:18 Functions: 7 30 23.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsStyleUtil.h"
       7             : #include "nsStyleConsts.h"
       8             : 
       9             : #include "nsIContent.h"
      10             : #include "nsCSSProps.h"
      11             : #include "nsContentUtils.h"
      12             : #include "nsRuleNode.h"
      13             : #include "nsROCSSPrimitiveValue.h"
      14             : #include "nsStyleStruct.h"
      15             : #include "nsIContentPolicy.h"
      16             : #include "nsIContentSecurityPolicy.h"
      17             : #include "nsIURI.h"
      18             : #include "nsPrintfCString.h"
      19             : #include <cctype>
      20             : 
      21             : using namespace mozilla;
      22             : 
      23             : //------------------------------------------------------------------------------
      24             : // Font Algorithm Code
      25             : //------------------------------------------------------------------------------
      26             : 
      27             : // Compare two language strings
      28           0 : bool nsStyleUtil::DashMatchCompare(const nsAString& aAttributeValue,
      29             :                                      const nsAString& aSelectorValue,
      30             :                                      const nsStringComparator& aComparator)
      31             : {
      32             :   bool result;
      33           0 :   uint32_t selectorLen = aSelectorValue.Length();
      34           0 :   uint32_t attributeLen = aAttributeValue.Length();
      35           0 :   if (selectorLen > attributeLen) {
      36           0 :     result = false;
      37             :   }
      38             :   else {
      39           0 :     nsAString::const_iterator iter;
      40           0 :     if (selectorLen != attributeLen &&
      41           0 :         *aAttributeValue.BeginReading(iter).advance(selectorLen) !=
      42             :             char16_t('-')) {
      43             :       // to match, the aAttributeValue must have a dash after the end of
      44             :       // the aSelectorValue's text (unless the aSelectorValue and the
      45             :       // aAttributeValue have the same text)
      46           0 :       result = false;
      47             :     }
      48             :     else {
      49           0 :       result = StringBeginsWith(aAttributeValue, aSelectorValue, aComparator);
      50             :     }
      51             :   }
      52           0 :   return result;
      53             : }
      54             : 
      55             : bool
      56         182 : nsStyleUtil::ValueIncludes(const nsAString& aValueList,
      57             :                            const nsAString& aValue,
      58             :                            const nsStringComparator& aComparator)
      59             : {
      60         182 :   const char16_t *p = aValueList.BeginReading(),
      61         182 :               *p_end = aValueList.EndReading();
      62             : 
      63         262 :   while (p < p_end) {
      64             :     // skip leading space
      65          50 :     while (p != p_end && nsContentUtils::IsHTMLWhitespace(*p))
      66           0 :       ++p;
      67             : 
      68          50 :     const char16_t *val_start = p;
      69             : 
      70             :     // look for space or end
      71        1134 :     while (p != p_end && !nsContentUtils::IsHTMLWhitespace(*p))
      72         542 :       ++p;
      73             : 
      74          50 :     const char16_t *val_end = p;
      75             : 
      76         200 :     if (val_start < val_end &&
      77         200 :         aValue.Equals(Substring(val_start, val_end), aComparator))
      78          10 :       return true;
      79             : 
      80          40 :     ++p; // we know the next character is not whitespace
      81             :   }
      82         172 :   return false;
      83             : }
      84             : 
      85           0 : void nsStyleUtil::AppendEscapedCSSString(const nsAString& aString,
      86             :                                          nsAString& aReturn,
      87             :                                          char16_t quoteChar)
      88             : {
      89           0 :   NS_PRECONDITION(quoteChar == '\'' || quoteChar == '"',
      90             :                   "CSS strings must be quoted with ' or \"");
      91           0 :   aReturn.Append(quoteChar);
      92             : 
      93           0 :   const char16_t* in = aString.BeginReading();
      94           0 :   const char16_t* const end = aString.EndReading();
      95           0 :   for (; in != end; in++) {
      96           0 :     if (*in < 0x20 || (*in >= 0x7F && *in < 0xA0)) {
      97             :       // Escape U+0000 through U+001F and U+007F through U+009F numerically.
      98           0 :       aReturn.AppendPrintf("\\%x ", *in);
      99             :     } else {
     100           0 :       if (*in == '"' || *in == '\'' || *in == '\\') {
     101             :         // Escape backslash and quote characters symbolically.
     102             :         // It's not technically necessary to escape the quote
     103             :         // character that isn't being used to delimit the string,
     104             :         // but we do it anyway because that makes testing simpler.
     105           0 :         aReturn.Append(char16_t('\\'));
     106             :       }
     107           0 :       aReturn.Append(*in);
     108             :     }
     109             :   }
     110             : 
     111           0 :   aReturn.Append(quoteChar);
     112           0 : }
     113             : 
     114             : /* static */ void
     115          66 : nsStyleUtil::AppendEscapedCSSIdent(const nsAString& aIdent, nsAString& aReturn)
     116             : {
     117             :   // The relevant parts of the CSS grammar are:
     118             :   //   ident    ([-]?{nmstart}|[-][-]){nmchar}*
     119             :   //   nmstart  [_a-z]|{nonascii}|{escape}
     120             :   //   nmchar   [_a-z0-9-]|{nonascii}|{escape}
     121             :   //   nonascii [^\0-\177]
     122             :   //   escape   {unicode}|\\[^\n\r\f0-9a-f]
     123             :   //   unicode  \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
     124             :   // from http://www.w3.org/TR/CSS21/syndata.html#tokenization but
     125             :   // modified for idents by
     126             :   // http://dev.w3.org/csswg/cssom/#serialize-an-identifier and
     127             :   // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier
     128             : 
     129          66 :   const char16_t* in = aIdent.BeginReading();
     130          66 :   const char16_t* const end = aIdent.EndReading();
     131             : 
     132          66 :   if (in == end)
     133           0 :     return;
     134             : 
     135             :   // A leading dash does not need to be escaped as long as it is not the
     136             :   // *only* character in the identifier.
     137          66 :   if (*in == '-') {
     138           0 :     if (in + 1 == end) {
     139           0 :       aReturn.Append(char16_t('\\'));
     140           0 :       aReturn.Append(char16_t('-'));
     141           0 :       return;
     142             :     }
     143             : 
     144           0 :     aReturn.Append(char16_t('-'));
     145           0 :     ++in;
     146             :   }
     147             : 
     148             :   // Escape a digit at the start (including after a dash),
     149             :   // numerically.  If we didn't escape it numerically, it would get
     150             :   // interpreted as a numeric escape for the wrong character.
     151          66 :   if (in != end && ('0' <= *in && *in <= '9')) {
     152           0 :     aReturn.AppendPrintf("\\%x ", *in);
     153           0 :     ++in;
     154             :   }
     155             : 
     156         582 :   for (; in != end; ++in) {
     157         258 :     char16_t ch = *in;
     158         258 :     if (ch == 0x00) {
     159           0 :       aReturn.Append(char16_t(0xFFFD));
     160         258 :     } else if (ch < 0x20 || (0x7F <= ch && ch < 0xA0)) {
     161             :       // Escape U+0000 through U+001F and U+007F through U+009F numerically.
     162           0 :       aReturn.AppendPrintf("\\%x ", *in);
     163             :     } else {
     164             :       // Escape ASCII non-identifier printables as a backslash plus
     165             :       // the character.
     166         258 :       if (ch < 0x7F &&
     167         516 :           ch != '_' && ch != '-' &&
     168         774 :           (ch < '0' || '9' < ch) &&
     169         774 :           (ch < 'A' || 'Z' < ch) &&
     170         516 :           (ch < 'a' || 'z' < ch)) {
     171           0 :         aReturn.Append(char16_t('\\'));
     172             :       }
     173         258 :       aReturn.Append(ch);
     174             :     }
     175             :   }
     176             : }
     177             : 
     178             : // unquoted family names must be a sequence of idents
     179             : // so escape any parts that require escaping
     180             : static void
     181           0 : AppendUnquotedFamilyName(const nsAString& aFamilyName, nsAString& aResult)
     182             : {
     183             :   const char16_t *p, *p_end;
     184           0 :   aFamilyName.BeginReading(p);
     185           0 :   aFamilyName.EndReading(p_end);
     186             : 
     187           0 :    bool moreThanOne = false;
     188           0 :    while (p < p_end) {
     189           0 :      const char16_t* identStart = p;
     190           0 :      while (++p != p_end && *p != ' ')
     191             :        /* nothing */ ;
     192             : 
     193           0 :      nsDependentSubstring ident(identStart, p);
     194           0 :      if (!ident.IsEmpty()) {
     195           0 :        if (moreThanOne) {
     196           0 :          aResult.Append(' ');
     197             :        }
     198           0 :        nsStyleUtil::AppendEscapedCSSIdent(ident, aResult);
     199           0 :        moreThanOne = true;
     200             :      }
     201             : 
     202           0 :      ++p;
     203             :   }
     204           0 : }
     205             : 
     206             : /* static */ void
     207           0 : nsStyleUtil::AppendEscapedCSSFontFamilyList(
     208             :   const mozilla::FontFamilyList& aFamilyList,
     209             :   nsAString& aResult)
     210             : {
     211           0 :   const nsTArray<FontFamilyName>& fontlist = aFamilyList.GetFontlist();
     212           0 :   size_t i, len = fontlist.Length();
     213           0 :   for (i = 0; i < len; i++) {
     214           0 :     if (i != 0) {
     215           0 :       aResult.Append(',');
     216             :     }
     217           0 :     const FontFamilyName& name = fontlist[i];
     218           0 :     switch (name.mType) {
     219             :       case eFamily_named:
     220           0 :         AppendUnquotedFamilyName(name.mName, aResult);
     221           0 :         break;
     222             :       case eFamily_named_quoted:
     223           0 :         AppendEscapedCSSString(name.mName, aResult);
     224           0 :         break;
     225             :       default:
     226           0 :         name.AppendToString(aResult);
     227             :     }
     228             :   }
     229           0 : }
     230             : 
     231             : 
     232             : /* static */ void
     233           0 : nsStyleUtil::AppendBitmaskCSSValue(nsCSSPropertyID aProperty,
     234             :                                    int32_t aMaskedValue,
     235             :                                    int32_t aFirstMask,
     236             :                                    int32_t aLastMask,
     237             :                                    nsAString& aResult)
     238             : {
     239           0 :   for (int32_t mask = aFirstMask; mask <= aLastMask; mask <<= 1) {
     240           0 :     if (mask & aMaskedValue) {
     241           0 :       AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, mask),
     242           0 :                          aResult);
     243           0 :       aMaskedValue &= ~mask;
     244           0 :       if (aMaskedValue) { // more left
     245           0 :         aResult.Append(char16_t(' '));
     246             :       }
     247             :     }
     248             :   }
     249           0 :   MOZ_ASSERT(aMaskedValue == 0, "unexpected bit remaining in bitfield");
     250           0 : }
     251             : 
     252             : /* static */ void
     253           0 : nsStyleUtil::AppendAngleValue(const nsStyleCoord& aAngle, nsAString& aResult)
     254             : {
     255           0 :   MOZ_ASSERT(aAngle.IsAngleValue(), "Should have angle value");
     256             : 
     257             :   // Append number.
     258           0 :   AppendCSSNumber(aAngle.GetAngleValue(), aResult);
     259             : 
     260             :   // Append unit.
     261           0 :   switch (aAngle.GetUnit()) {
     262           0 :     case eStyleUnit_Degree: aResult.AppendLiteral("deg");  break;
     263           0 :     case eStyleUnit_Grad:   aResult.AppendLiteral("grad"); break;
     264           0 :     case eStyleUnit_Radian: aResult.AppendLiteral("rad");  break;
     265           0 :     case eStyleUnit_Turn:   aResult.AppendLiteral("turn"); break;
     266           0 :     default: NS_NOTREACHED("unrecognized angle unit");
     267             :   }
     268           0 : }
     269             : 
     270             : /* static */ void
     271           0 : nsStyleUtil::AppendPaintOrderValue(uint8_t aValue,
     272             :                                    nsAString& aResult)
     273             : {
     274             :   static_assert
     275             :     (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
     276             :      "SVGStyleStruct::mPaintOrder and local variables not big enough");
     277             : 
     278           0 :   if (aValue == NS_STYLE_PAINT_ORDER_NORMAL) {
     279           0 :     aResult.AppendLiteral("normal");
     280           0 :     return;
     281             :   }
     282             : 
     283             :   // Append the minimal value necessary for the given paint order.
     284             :   static_assert(NS_STYLE_PAINT_ORDER_LAST_VALUE == 3,
     285             :                 "paint-order values added; check serialization");
     286             : 
     287             :   // The following relies on the default order being the order of the
     288             :   // constant values.
     289             : 
     290           0 :   const uint8_t MASK = (1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1;
     291             : 
     292           0 :   uint32_t lastPositionToSerialize = 0;
     293           0 :   for (uint32_t position = NS_STYLE_PAINT_ORDER_LAST_VALUE - 1;
     294           0 :        position > 0;
     295             :        position--) {
     296             :     uint8_t component =
     297           0 :       (aValue >> (position * NS_STYLE_PAINT_ORDER_BITWIDTH)) & MASK;
     298             :     uint8_t earlierComponent =
     299           0 :       (aValue >> ((position - 1) * NS_STYLE_PAINT_ORDER_BITWIDTH)) & MASK;
     300           0 :     if (component < earlierComponent) {
     301           0 :       lastPositionToSerialize = position - 1;
     302           0 :       break;
     303             :     }
     304             :   }
     305             : 
     306           0 :   for (uint32_t position = 0; position <= lastPositionToSerialize; position++) {
     307           0 :     if (position > 0) {
     308           0 :       aResult.Append(' ');
     309             :     }
     310           0 :     uint8_t component = aValue & MASK;
     311           0 :     switch (component) {
     312             :       case NS_STYLE_PAINT_ORDER_FILL:
     313           0 :         aResult.AppendLiteral("fill");
     314           0 :         break;
     315             : 
     316             :       case NS_STYLE_PAINT_ORDER_STROKE:
     317           0 :         aResult.AppendLiteral("stroke");
     318           0 :         break;
     319             : 
     320             :       case NS_STYLE_PAINT_ORDER_MARKERS:
     321           0 :         aResult.AppendLiteral("markers");
     322           0 :         break;
     323             : 
     324             :       default:
     325           0 :         NS_NOTREACHED("unexpected paint-order component value");
     326             :     }
     327           0 :     aValue >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
     328             :   }
     329             : }
     330             : 
     331             : /* static */ void
     332           0 : nsStyleUtil::AppendFontTagAsString(uint32_t aTag, nsAString& aResult)
     333             : {
     334             :   // A font tag (for feature/variation settings) is a 4-char code interpreted
     335             :   // as a bigendian 32-bit value and stored/processed as a uint32_t.
     336             :   // To serialize it, we put the four bytes (which are all guaranteed to be
     337             :   // printable ASCII values) into a string, starting from the high byte of the
     338             :   // value, then append that to the result with CSS escaping and quotes.
     339           0 :   nsAutoString tagStr;
     340           0 :   for (int shiftAmount = 24; shiftAmount >= 0; shiftAmount -= 8) {
     341           0 :     char c = (aTag >> shiftAmount) & 0xff;
     342           0 :     MOZ_ASSERT(isascii(c) && isprint(c),
     343             :                "parser should have restricted tag to printable ASCII chars");
     344           0 :     tagStr.Append(c);
     345             :   }
     346           0 :   AppendEscapedCSSString(tagStr, aResult);
     347           0 : }
     348             : 
     349             : /* static */ void
     350           0 : nsStyleUtil::AppendFontFeatureSettings(const nsTArray<gfxFontFeature>& aFeatures,
     351             :                                        nsAString& aResult)
     352             : {
     353           0 :   for (uint32_t i = 0, numFeat = aFeatures.Length(); i < numFeat; i++) {
     354           0 :     const gfxFontFeature& feat = aFeatures[i];
     355             : 
     356           0 :     if (i != 0) {
     357           0 :       aResult.AppendLiteral(", ");
     358             :     }
     359             : 
     360           0 :     AppendFontTagAsString(feat.mTag, aResult);
     361             : 
     362             :     // output value, if necessary
     363           0 :     if (feat.mValue == 0) {
     364             :       // 0 ==> off
     365           0 :       aResult.AppendLiteral(" off");
     366           0 :     } else if (feat.mValue > 1) {
     367           0 :       aResult.Append(' ');
     368           0 :       aResult.AppendInt(feat.mValue);
     369             :     }
     370             :     // else, omit value if 1, implied by default
     371             :   }
     372           0 : }
     373             : 
     374             : /* static */ void
     375           0 : nsStyleUtil::AppendFontFeatureSettings(const nsCSSValue& aSrc,
     376             :                                        nsAString& aResult)
     377             : {
     378           0 :   nsCSSUnit unit = aSrc.GetUnit();
     379             : 
     380           0 :   if (unit == eCSSUnit_Normal) {
     381           0 :     aResult.AppendLiteral("normal");
     382           0 :     return;
     383             :   }
     384             : 
     385           0 :   NS_PRECONDITION(unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep,
     386             :                   "improper value unit for font-feature-settings:");
     387             : 
     388           0 :   nsTArray<gfxFontFeature> featureSettings;
     389           0 :   nsRuleNode::ComputeFontFeatures(aSrc.GetPairListValue(), featureSettings);
     390           0 :   AppendFontFeatureSettings(featureSettings, aResult);
     391             : }
     392             : 
     393             : /* static */ void
     394           0 : nsStyleUtil::AppendFontVariationSettings(const nsTArray<gfxFontVariation>& aVariations,
     395             :                                          nsAString& aResult)
     396             : {
     397           0 :   for (uint32_t i = 0, numVars = aVariations.Length(); i < numVars; i++) {
     398           0 :     const gfxFontVariation& var = aVariations[i];
     399             : 
     400           0 :     if (i != 0) {
     401           0 :       aResult.AppendLiteral(", ");
     402             :     }
     403             : 
     404             :     // output tag
     405           0 :     AppendFontTagAsString(var.mTag, aResult);
     406             : 
     407             :     // output value
     408           0 :     aResult.Append(' ');
     409           0 :     aResult.AppendFloat(var.mValue);
     410             :   }
     411           0 : }
     412             : 
     413             : /* static */ void
     414           0 : nsStyleUtil::AppendFontVariationSettings(const nsCSSValue& aSrc,
     415             :                                          nsAString& aResult)
     416             : {
     417           0 :   nsCSSUnit unit = aSrc.GetUnit();
     418             : 
     419           0 :   if (unit == eCSSUnit_Normal) {
     420           0 :     aResult.AppendLiteral("normal");
     421           0 :     return;
     422             :   }
     423             : 
     424           0 :   NS_PRECONDITION(unit == eCSSUnit_PairList || unit == eCSSUnit_PairListDep,
     425             :                   "improper value unit for font-variation-settings:");
     426             : 
     427           0 :   nsTArray<gfxFontVariation> variationSettings;
     428           0 :   nsRuleNode::ComputeFontVariations(aSrc.GetPairListValue(), variationSettings);
     429           0 :   AppendFontVariationSettings(variationSettings, aResult);
     430             : }
     431             : 
     432             : /* static */ void
     433           0 : nsStyleUtil::GetFunctionalAlternatesName(int32_t aFeature,
     434             :                                          nsAString& aFeatureName)
     435             : {
     436           0 :   aFeatureName.Truncate();
     437             :   nsCSSKeyword key =
     438             :     nsCSSProps::ValueToKeywordEnum(aFeature,
     439           0 :                            nsCSSProps::kFontVariantAlternatesFuncsKTable);
     440             : 
     441           0 :   NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "bad alternate feature type");
     442           0 :   AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(key), aFeatureName);
     443           0 : }
     444             : 
     445             : /* static */ void
     446           0 : nsStyleUtil::SerializeFunctionalAlternates(
     447             :     const nsTArray<gfxAlternateValue>& aAlternates,
     448             :     nsAString& aResult)
     449             : {
     450           0 :   nsAutoString funcName, funcParams;
     451           0 :   uint32_t numValues = aAlternates.Length();
     452             : 
     453           0 :   uint32_t feature = 0;
     454           0 :   for (uint32_t i = 0; i < numValues; i++) {
     455           0 :     const gfxAlternateValue& v = aAlternates.ElementAt(i);
     456           0 :     if (feature != v.alternate) {
     457           0 :       feature = v.alternate;
     458           0 :       if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
     459           0 :         if (!aResult.IsEmpty()) {
     460           0 :           aResult.Append(char16_t(' '));
     461             :         }
     462             : 
     463             :         // append the previous functional value
     464           0 :         aResult.Append(funcName);
     465           0 :         aResult.Append(char16_t('('));
     466           0 :         aResult.Append(funcParams);
     467           0 :         aResult.Append(char16_t(')'));
     468             :       }
     469             : 
     470             :       // function name
     471           0 :       GetFunctionalAlternatesName(v.alternate, funcName);
     472           0 :       NS_ASSERTION(!funcName.IsEmpty(), "unknown property value name");
     473             : 
     474             :       // function params
     475           0 :       funcParams.Truncate();
     476           0 :       AppendEscapedCSSIdent(v.value, funcParams);
     477             :     } else {
     478           0 :       if (!funcParams.IsEmpty()) {
     479           0 :         funcParams.AppendLiteral(", ");
     480             :       }
     481           0 :       AppendEscapedCSSIdent(v.value, funcParams);
     482             :     }
     483             :   }
     484             : 
     485             :     // append the previous functional value
     486           0 :   if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
     487           0 :     if (!aResult.IsEmpty()) {
     488           0 :       aResult.Append(char16_t(' '));
     489             :     }
     490             : 
     491           0 :     aResult.Append(funcName);
     492           0 :     aResult.Append(char16_t('('));
     493           0 :     aResult.Append(funcParams);
     494           0 :     aResult.Append(char16_t(')'));
     495             :   }
     496           0 : }
     497             : 
     498             : /* static */ void
     499           0 : nsStyleUtil::ComputeFunctionalAlternates(const nsCSSValueList* aList,
     500             :                                   nsTArray<gfxAlternateValue>& aAlternateValues)
     501             : {
     502           0 :   gfxAlternateValue v;
     503             : 
     504           0 :   aAlternateValues.Clear();
     505           0 :   for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
     506             :     // list contains function units
     507           0 :     if (curr->mValue.GetUnit() != eCSSUnit_Function) {
     508           0 :       continue;
     509             :     }
     510             : 
     511             :     // element 0 is the propval in ident form
     512           0 :     const nsCSSValue::Array *func = curr->mValue.GetArrayValue();
     513             : 
     514             :     // lookup propval
     515           0 :     nsCSSKeyword key = func->Item(0).GetKeywordValue();
     516           0 :     NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "unknown alternate property value");
     517             : 
     518             :     int32_t alternate;
     519           0 :     if (!nsCSSProps::FindKeyword(key,
     520             :                                  nsCSSProps::kFontVariantAlternatesFuncsKTable,
     521             :                                  alternate)) {
     522           0 :       NS_NOTREACHED("keyword not a font-variant-alternates value");
     523           0 :       continue;
     524             :     }
     525           0 :     v.alternate = alternate;
     526             : 
     527             :     // other elements are the idents associated with the propval
     528             :     // append one alternate value for each one
     529           0 :     uint32_t numElems = func->Count();
     530           0 :     for (uint32_t i = 1; i < numElems; i++) {
     531           0 :       const nsCSSValue& value = func->Item(i);
     532           0 :       NS_ASSERTION(value.GetUnit() == eCSSUnit_Ident,
     533             :                    "weird unit found in variant alternate");
     534           0 :       if (value.GetUnit() != eCSSUnit_Ident) {
     535           0 :         continue;
     536             :       }
     537           0 :       value.GetStringValue(v.value);
     538           0 :       aAlternateValues.AppendElement(v);
     539             :     }
     540             :   }
     541           0 : }
     542             : 
     543             : static void
     544           0 : AppendSerializedUnicodePoint(uint32_t aCode, nsACString& aBuf)
     545             : {
     546           0 :   aBuf.Append(nsPrintfCString("%0X", aCode));
     547           0 : }
     548             : 
     549             : // A unicode-range: descriptor is represented as an array of integers,
     550             : // to be interpreted as a sequence of pairs: min max min max ...
     551             : // It is in source order.  (Possibly it should be sorted and overlaps
     552             : // consolidated, but right now we don't do that.)
     553             : /* static */ void
     554           0 : nsStyleUtil::AppendUnicodeRange(const nsCSSValue& aValue, nsAString& aResult)
     555             : {
     556           0 :   NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Null ||
     557             :                   aValue.GetUnit() == eCSSUnit_Array,
     558             :                   "improper value unit for unicode-range:");
     559           0 :   aResult.Truncate();
     560           0 :   if (aValue.GetUnit() != eCSSUnit_Array)
     561           0 :     return;
     562             : 
     563           0 :   nsCSSValue::Array const & sources = *aValue.GetArrayValue();
     564           0 :   nsAutoCString buf;
     565             : 
     566           0 :   MOZ_ASSERT(sources.Count() % 2 == 0,
     567             :              "odd number of entries in a unicode-range: array");
     568             : 
     569           0 :   for (uint32_t i = 0; i < sources.Count(); i += 2) {
     570           0 :     uint32_t min = sources[i].GetIntValue();
     571           0 :     uint32_t max = sources[i+1].GetIntValue();
     572             : 
     573             :     // We don't try to replicate the U+XX?? notation.
     574           0 :     buf.AppendLiteral("U+");
     575           0 :     AppendSerializedUnicodePoint(min, buf);
     576             : 
     577           0 :     if (min != max) {
     578           0 :       buf.Append('-');
     579           0 :       AppendSerializedUnicodePoint(max, buf);
     580             :     }
     581           0 :     buf.AppendLiteral(", ");
     582             :   }
     583           0 :   buf.Truncate(buf.Length() - 2); // remove the last comma-space
     584           0 :   CopyASCIItoUTF16(buf, aResult);
     585             : }
     586             : 
     587             : /* static */ void
     588           0 : nsStyleUtil::AppendSerializedFontSrc(const nsCSSValue& aValue,
     589             :                                      nsAString& aResult)
     590             : {
     591             :   // A src: descriptor is represented as an array value; each entry in
     592             :   // the array can be eCSSUnit_URL, eCSSUnit_Local_Font, or
     593             :   // eCSSUnit_Font_Format.  Blocks of eCSSUnit_Font_Format may appear
     594             :   // only after one of the first two.  (css3-fonts only contemplates
     595             :   // annotating URLs with formats, but we handle the general case.)
     596             : 
     597           0 :   NS_PRECONDITION(aValue.GetUnit() == eCSSUnit_Array,
     598             :                   "improper value unit for src:");
     599             : 
     600           0 :   const nsCSSValue::Array& sources = *aValue.GetArrayValue();
     601           0 :   size_t i = 0;
     602             : 
     603           0 :   while (i < sources.Count()) {
     604           0 :     nsAutoString formats;
     605             : 
     606           0 :     if (sources[i].GetUnit() == eCSSUnit_URL) {
     607           0 :       aResult.AppendLiteral("url(");
     608           0 :       nsDependentString url(sources[i].GetOriginalURLValue());
     609           0 :       nsStyleUtil::AppendEscapedCSSString(url, aResult);
     610           0 :       aResult.Append(')');
     611           0 :     } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
     612           0 :       aResult.AppendLiteral("local(");
     613           0 :       nsDependentString local(sources[i].GetStringBufferValue());
     614           0 :       nsStyleUtil::AppendEscapedCSSString(local, aResult);
     615           0 :       aResult.Append(')');
     616             :     } else {
     617           0 :       NS_NOTREACHED("entry in src: descriptor with improper unit");
     618           0 :       i++;
     619           0 :       continue;
     620             :     }
     621             : 
     622           0 :     i++;
     623           0 :     formats.Truncate();
     624           0 :     while (i < sources.Count() &&
     625           0 :            sources[i].GetUnit() == eCSSUnit_Font_Format) {
     626           0 :       formats.Append('"');
     627           0 :       formats.Append(sources[i].GetStringBufferValue());
     628           0 :       formats.AppendLiteral("\", ");
     629           0 :       i++;
     630             :     }
     631           0 :     if (formats.Length() > 0) {
     632           0 :       formats.Truncate(formats.Length() - 2); // remove the last comma
     633           0 :       aResult.AppendLiteral(" format(");
     634           0 :       aResult.Append(formats);
     635           0 :       aResult.Append(')');
     636             :     }
     637           0 :     aResult.AppendLiteral(", ");
     638             :   }
     639           0 :   aResult.Truncate(aResult.Length() - 2); // remove the last comma-space
     640           0 : }
     641             : 
     642             : /* static */ void
     643           0 : nsStyleUtil::AppendStepsTimingFunction(nsTimingFunction::Type aType,
     644             :                                        uint32_t aSteps,
     645             :                                        nsAString& aResult)
     646             : {
     647           0 :   MOZ_ASSERT(aType == nsTimingFunction::Type::StepStart ||
     648             :              aType == nsTimingFunction::Type::StepEnd);
     649             : 
     650           0 :   aResult.AppendLiteral("steps(");
     651           0 :   aResult.AppendInt(aSteps);
     652           0 :   if (aType == nsTimingFunction::Type::StepStart) {
     653           0 :     aResult.AppendLiteral(", start)");
     654             :   } else {
     655           0 :     aResult.AppendLiteral(")");
     656             :   }
     657           0 : }
     658             : 
     659             : /* static */ void
     660           0 : nsStyleUtil::AppendFramesTimingFunction(uint32_t aFrames,
     661             :                                         nsAString& aResult)
     662             : {
     663           0 :   aResult.AppendLiteral("frames(");
     664           0 :   aResult.AppendInt(aFrames);
     665           0 :   aResult.AppendLiteral(")");
     666           0 : }
     667             : 
     668             : /* static */ void
     669           0 : nsStyleUtil::AppendCubicBezierTimingFunction(float aX1, float aY1,
     670             :                                              float aX2, float aY2,
     671             :                                              nsAString& aResult)
     672             : {
     673             :   // set the value from the cubic-bezier control points
     674             :   // (We could try to regenerate the keywords if we want.)
     675           0 :   aResult.AppendLiteral("cubic-bezier(");
     676           0 :   aResult.AppendFloat(aX1);
     677           0 :   aResult.AppendLiteral(", ");
     678           0 :   aResult.AppendFloat(aY1);
     679           0 :   aResult.AppendLiteral(", ");
     680           0 :   aResult.AppendFloat(aX2);
     681           0 :   aResult.AppendLiteral(", ");
     682           0 :   aResult.AppendFloat(aY2);
     683           0 :   aResult.Append(')');
     684           0 : }
     685             : 
     686             : /* static */ void
     687           0 : nsStyleUtil::AppendCubicBezierKeywordTimingFunction(
     688             :     nsTimingFunction::Type aType,
     689             :     nsAString& aResult)
     690             : {
     691           0 :   switch (aType) {
     692             :     case nsTimingFunction::Type::Ease:
     693             :     case nsTimingFunction::Type::Linear:
     694             :     case nsTimingFunction::Type::EaseIn:
     695             :     case nsTimingFunction::Type::EaseOut:
     696             :     case nsTimingFunction::Type::EaseInOut: {
     697             :       nsCSSKeyword keyword = nsCSSProps::ValueToKeywordEnum(
     698             :           static_cast<int32_t>(aType),
     699           0 :           nsCSSProps::kTransitionTimingFunctionKTable);
     700           0 :       AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(keyword),
     701           0 :                          aResult);
     702           0 :       break;
     703             :     }
     704             :     default:
     705           0 :       MOZ_ASSERT_UNREACHABLE("unexpected aType");
     706             :       break;
     707             :   }
     708           0 : }
     709             : 
     710             : /* static */ float
     711           3 : nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
     712             : {
     713             :   // Alpha values are expressed as decimals, so we should convert
     714             :   // back, using as few decimal places as possible for
     715             :   // round-tripping.
     716             :   // First try two decimal places:
     717           3 :   float rounded = NS_roundf(float(aAlpha) * 100.0f / 255.0f) / 100.0f;
     718           3 :   if (FloatToColorComponent(rounded) != aAlpha) {
     719             :     // Use three decimal places.
     720           0 :     rounded = NS_roundf(float(aAlpha) * 1000.0f / 255.0f) / 1000.0f;
     721             :   }
     722           3 :   return rounded;
     723             : }
     724             : 
     725             : /* static */ bool
     726          38 : nsStyleUtil::IsSignificantChild(nsIContent* aChild, bool aTextIsSignificant,
     727             :                                 bool aWhitespaceIsSignificant)
     728             : {
     729          38 :   NS_ASSERTION(!aWhitespaceIsSignificant || aTextIsSignificant,
     730             :                "Nonsensical arguments");
     731             : 
     732          38 :   bool isText = aChild->IsNodeOfType(nsINode::eTEXT);
     733             : 
     734          76 :   if (!isText && !aChild->IsNodeOfType(nsINode::eCOMMENT) &&
     735          38 :       !aChild->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     736          38 :     return true;
     737             :   }
     738             : 
     739           0 :   return aTextIsSignificant && isText && aChild->TextLength() != 0 &&
     740           0 :          (aWhitespaceIsSignificant ||
     741           0 :           !aChild->TextIsOnlyWhitespace());
     742             : }
     743             : 
     744             : /* static */ bool
     745           0 : nsStyleUtil::ThreadSafeIsSignificantChild(const nsIContent* aChild,
     746             :                                           bool aTextIsSignificant,
     747             :                                           bool aWhitespaceIsSignificant)
     748             : {
     749           0 :   NS_ASSERTION(!aWhitespaceIsSignificant || aTextIsSignificant,
     750             :                "Nonsensical arguments");
     751             : 
     752           0 :   bool isText = aChild->IsNodeOfType(nsINode::eTEXT);
     753             : 
     754           0 :   if (!isText && !aChild->IsNodeOfType(nsINode::eCOMMENT) &&
     755           0 :       !aChild->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     756           0 :     return true;
     757             :   }
     758             : 
     759           0 :   return aTextIsSignificant && isText && aChild->TextLength() != 0 &&
     760           0 :          (aWhitespaceIsSignificant ||
     761           0 :           !aChild->ThreadSafeTextIsOnlyWhitespace());
     762             : }
     763             : 
     764             : // For a replaced element whose concrete object size is no larger than the
     765             : // element's content-box, this method checks whether the given
     766             : // "object-position" coordinate might cause overflow in its dimension.
     767             : static bool
     768         682 : ObjectPositionCoordMightCauseOverflow(const Position::Coord& aCoord)
     769             : {
     770             :   // Any nonzero length in "object-position" can push us to overflow
     771             :   // (particularly if our concrete object size is exactly the same size as the
     772             :   // replaced element's content-box).
     773         682 :   if (aCoord.mLength != 0) {
     774           0 :     return true;
     775             :   }
     776             : 
     777             :   // Percentages are interpreted as a fraction of the extra space. So,
     778             :   // percentages in the 0-100% range are safe, but values outside of that
     779             :   // range could cause overflow.
     780        1364 :   if (aCoord.mHasPercent &&
     781        1364 :       (aCoord.mPercent < 0.0f || aCoord.mPercent > 1.0f)) {
     782           0 :     return true;
     783             :   }
     784         682 :   return false;
     785             : }
     786             : 
     787             : 
     788             : /* static */ bool
     789         341 : nsStyleUtil::ObjectPropsMightCauseOverflow(const nsStylePosition* aStylePos)
     790             : {
     791         341 :   auto objectFit = aStylePos->mObjectFit;
     792             : 
     793             :   // "object-fit: cover" & "object-fit: none" can give us a render rect that's
     794             :   // larger than our container element's content-box.
     795         341 :   if (objectFit == NS_STYLE_OBJECT_FIT_COVER ||
     796             :       objectFit == NS_STYLE_OBJECT_FIT_NONE) {
     797           0 :     return true;
     798             :   }
     799             :   // (All other object-fit values produce a concrete object size that's no larger
     800             :   // than the constraint region.)
     801             : 
     802             :   // Check each of our "object-position" coords to see if it could cause
     803             :   // overflow in its dimension:
     804         341 :   const Position& objectPosistion = aStylePos->mObjectPosition;
     805         682 :   if (ObjectPositionCoordMightCauseOverflow(objectPosistion.mXPosition) ||
     806         341 :       ObjectPositionCoordMightCauseOverflow(objectPosistion.mYPosition)) {
     807           0 :     return true;
     808             :   }
     809             : 
     810         341 :   return false;
     811             : }
     812             : 
     813             : 
     814             : /* static */ bool
     815           5 : nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
     816             :                                   nsIPrincipal* aPrincipal,
     817             :                                   nsIURI* aSourceURI,
     818             :                                   uint32_t aLineNumber,
     819             :                                   const nsAString& aStyleText,
     820             :                                   nsresult* aRv)
     821             : {
     822             :   nsresult rv;
     823             : 
     824           5 :   if (aRv) {
     825           5 :     *aRv = NS_OK;
     826             :   }
     827             : 
     828           5 :   MOZ_ASSERT(!aContent || aContent->NodeInfo()->NameAtom() == nsGkAtoms::style,
     829             :       "aContent passed to CSPAllowsInlineStyle "
     830             :       "for an element that is not <style>");
     831             : 
     832          10 :   nsCOMPtr<nsIContentSecurityPolicy> csp;
     833           5 :   rv = aPrincipal->GetCsp(getter_AddRefs(csp));
     834             : 
     835           5 :   if (NS_FAILED(rv)) {
     836           0 :     if (aRv)
     837           0 :       *aRv = rv;
     838           0 :     return false;
     839             :   }
     840             : 
     841           5 :   if (!csp) {
     842             :     // No CSP --> the style is allowed
     843           5 :     return true;
     844             :   }
     845             : 
     846             :   // query the nonce
     847           0 :   nsAutoString nonce;
     848           0 :   if (aContent) {
     849           0 :     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::nonce, nonce);
     850             :   }
     851             : 
     852           0 :   bool allowInlineStyle = true;
     853           0 :   rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_STYLESHEET,
     854             :                             nonce,
     855             :                             false, // aParserCreated only applies to scripts
     856             :                             aStyleText, aLineNumber,
     857           0 :                             &allowInlineStyle);
     858           0 :   NS_ENSURE_SUCCESS(rv, false);
     859             : 
     860           0 :   return allowInlineStyle;
     861             : }

Generated by: LCOV version 1.13