/* static */ bool nsMathMLElement::ParseNamedSpaceValue(const nsString& aString, nsCSSValue& aCSSValue, uint32_t aFlags) { int32_t i = 0; // See if it is one of the 'namedspace' (ranging -7/18em, -6/18, ... 7/18em) if (aString.EqualsLiteral("veryverythinmathspace")) { i = 1; } else if (aString.EqualsLiteral("verythinmathspace")) { i = 2; } else if (aString.EqualsLiteral("thinmathspace")) { i = 3; } else if (aString.EqualsLiteral("mediummathspace")) { i = 4; } else if (aString.EqualsLiteral("thickmathspace")) { i = 5; } else if (aString.EqualsLiteral("verythickmathspace")) { i = 6; } else if (aString.EqualsLiteral("veryverythickmathspace")) { i = 7; } else if (aFlags & PARSE_ALLOW_NEGATIVE) { if (aString.EqualsLiteral("negativeveryverythinmathspace")) { i = -1; } else if (aString.EqualsLiteral("negativeverythinmathspace")) { i = -2; } else if (aString.EqualsLiteral("negativethinmathspace")) { i = -3; } else if (aString.EqualsLiteral("negativemediummathspace")) { i = -4; } else if (aString.EqualsLiteral("negativethickmathspace")) { i = -5; } else if (aString.EqualsLiteral("negativeverythickmathspace")) { i = -6; } else if (aString.EqualsLiteral("negativeveryverythickmathspace")) { i = -7; } } if (0 != i) { aCSSValue.SetFloatValue(float(i)/float(18), eCSSUnit_EM); return true; } return false; }
static nsresult GetColor(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { // FIXME: This implementation is bogus. nsDeviceContext // doesn't provide reliable information (should be fixed in bug // 424386). // FIXME: On a monochrome device, return 0! nsDeviceContext *dx = GetDeviceContextFor(aPresContext); uint32_t depth; dx->GetDepth(depth); // The spec says to use bits *per color component*, so divide by 3, // and round down, since the spec says to use the smallest when the // color components differ. depth /= 3; aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer); return NS_OK; }
static nsresult GetResolution(nsPresContext* aPresContext, const nsMediaFeature*, nsCSSValue& aResult) { // Resolution measures device pixels per CSS (inch/cm/pixel). We // return it in device pixels per CSS inches. // // However, on platforms where the CSS viewport is not fixed to the // screen viewport, use the device resolution instead (bug 779527). nsIPresShell *shell = aPresContext->PresShell(); float appUnitsPerInch = shell->GetIsViewportOverridden() ? GetDeviceContextFor(aPresContext)->AppUnitsPerPhysicalInch() : nsPresContext::AppUnitsPerCSSInch(); float dpi = appUnitsPerInch / float(aPresContext->AppUnitsPerDevPixel()); aResult.SetFloatValue(dpi, eCSSUnit_Inch); return NS_OK; }
void nsCSSValue::SetPairValue(const nsCSSValue& xValue, const nsCSSValue& yValue) { NS_ABORT_IF_FALSE(xValue.GetUnit() != eCSSUnit_Null && yValue.GetUnit() != eCSSUnit_Null && xValue.GetUnit() != eCSSUnit_Inherit && yValue.GetUnit() != eCSSUnit_Inherit && xValue.GetUnit() != eCSSUnit_Initial && yValue.GetUnit() != eCSSUnit_Initial, "inappropriate pair value"); Reset(); mUnit = eCSSUnit_Pair; mValue.mPair = new nsCSSValuePair_heap(xValue, yValue); mValue.mPair->AddRef(); }
static void GetColor(nsIDocument* aDocument, const nsMediaFeature*, nsCSSValue& aResult) { // Use depth of 24 when resisting fingerprinting, or when we're not being // rendered. uint32_t depth = 24; if (!nsContentUtils::ShouldResistFingerprinting(aDocument)) { if (nsDeviceContext* dx = GetDeviceContextFor(aDocument)) { // FIXME: On a monochrome device, return 0! dx->GetDepth(depth); } } // The spec says to use bits *per color component*, so divide by 3, // and round down, since the spec says to use the smallest when the // color components differ. depth /= 3; aResult.SetIntValue(int32_t(depth), eCSSUnit_Integer); }
static void GetResolution(nsIDocument* aDocument, const nsMediaFeature*, nsCSSValue& aResult) { // We're returning resolution in terms of device pixels per css pixel, since // that is the preferred unit for media queries of resolution. This avoids // introducing precision error from conversion to and from less-used // physical units like inches. float dppx = 1.; if (nsDeviceContext* dx = GetDeviceContextFor(aDocument)) { if (nsContentUtils::ShouldResistFingerprinting(aDocument)) { dppx = dx->GetFullZoom(); } else { // Get the actual device pixel ratio, which also takes zoom into account. dppx = float(nsPresContext::AppUnitsPerCSSPixel()) / dx->AppUnitsPerDevPixel(); } } aResult.SetFloatValue(dppx, eCSSUnit_Pixel); }
/** * Tries to call |nsCSSValue::StartImageLoad()| on an image source. * Image sources are specified by |url()| or |-moz-image-rect()| function. */ static void TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument) { MOZ_ASSERT(aDocument); if (aValue.GetUnit() == eCSSUnit_URL) { aValue.StartImageLoad(aDocument); } else if (aValue.GetUnit() == eCSSUnit_Image) { // If we already have a request, see if this document needs to clone it. imgIRequest* request = aValue.GetImageValue(nullptr); if (request) { aDocument->StyleImageLoader()->MaybeRegisterCSSImage(aValue.GetImageStructValue()); } } else if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) { nsCSSValue::Array* arguments = aValue.GetArrayValue(); NS_ABORT_IF_FALSE(arguments->Count() == 6, "unexpected num of arguments"); const nsCSSValue& image = arguments->Item(1); TryToStartImageLoadOnValue(image, aDocument); } }
// The REC says: // // "Most presentation elements have attributes that accept values representing // lengths to be used for size, spacing or similar properties. The syntax of a // length is specified as // // number | number unit | namedspace // // There should be no space between the number and the unit of a length." // // "A trailing '%' represents a percent of the default value. The default // value, or how it is obtained, is listed in the table of attributes for each // element. [...] A number without a unit is intepreted as a multiple of the // default value." // // "The possible units in MathML are: // // Unit Description // em an em (font-relative unit traditionally used for horizontal lengths) // ex an ex (font-relative unit traditionally used for vertical lengths) // px pixels, or size of a pixel in the current display // in inches (1 inch = 2.54 centimeters) // cm centimeters // mm millimeters // pt points (1 point = 1/72 inch) // pc picas (1 pica = 12 points) // % percentage of default value" // // The numbers are defined that way: // - unsigned-number: "a string of decimal digits with up to one decimal point // (U+002E), representing a non-negative terminating decimal number (a type of // rational number)" // - number: "an optional prefix of '-' (U+002D), followed by an unsigned // number, representing a terminating decimal number (a type of rational // number)" // /* static */ bool nsMathMLElement::ParseNumericValue(const nsString& aString, nsCSSValue& aCSSValue, uint32_t aFlags, nsIDocument* aDocument) { nsAutoString str(aString); str.CompressWhitespace(); // aString is const in this code... int32_t stringLength = str.Length(); if (!stringLength) { if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; } if (ParseNamedSpaceValue(aString, aCSSValue, aFlags)) { return true; } nsAutoString number, unit; // see if the negative sign is there int32_t i = 0; PRUnichar c = str[0]; if (c == '-') { number.Append(c); i++; } // Gather up characters that make up the number bool gotDot = false; for ( ; i < stringLength; i++) { c = str[i]; if (gotDot && c == '.') { if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; // two dots encountered } else if (c == '.') gotDot = true; else if (!nsCRT::IsAsciiDigit(c)) { str.Right(unit, stringLength - i); // some authors leave blanks before the unit, but that shouldn't // be allowed, so don't CompressWhitespace on 'unit'. break; } number.Append(c); } // Convert number to floating point nsresult errorCode; float floatValue = number.ToFloat(&errorCode); if (NS_FAILED(errorCode)) { if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; } if (floatValue < 0 && !(aFlags & PARSE_ALLOW_NEGATIVE)) { if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; } nsCSSUnit cssUnit; if (unit.IsEmpty()) { if (aFlags & PARSE_ALLOW_UNITLESS) { // no explicit unit, this is a number that will act as a multiplier if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("MathML"), aDocument, nsContentUtils::eMATHML_PROPERTIES, "UnitlessValuesAreDeprecated"); } if (aFlags & CONVERT_UNITLESS_TO_PERCENT) { aCSSValue.SetPercentValue(floatValue); return true; } else cssUnit = eCSSUnit_Number; } else { // We are supposed to have a unit, but there isn't one. // If the value is 0 we can just call it "pixels" otherwise // this is illegal. if (floatValue != 0.0) { if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; } cssUnit = eCSSUnit_Pixel; } } else if (unit.EqualsLiteral("%")) { aCSSValue.SetPercentValue(floatValue / 100.0f); return true; } else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM; else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight; else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel; else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch; else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter; else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter; else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point; else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica; else { // unexpected unit if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) { ReportLengthParseError(aString, aDocument); } return false; } aCSSValue.SetFloatValue(floatValue, cssUnit); return true; }
void nsMathMLmpaddedFrame::UpdateValue(PRInt32 aSign, PRInt32 aPseudoUnit, const nsCSSValue& aCSSValue, nscoord aLeftSpace, const nsBoundingMetrics& aBoundingMetrics, nscoord& aValueToUpdate) const { nsCSSUnit unit = aCSSValue.GetUnit(); if (NS_MATHML_SIGN_INVALID != aSign && eCSSUnit_Null != unit) { nscoord scaler = 0, amount = 0; if (eCSSUnit_Percent == unit || eCSSUnit_Number == unit) { switch(aPseudoUnit) { case NS_MATHML_PSEUDO_UNIT_WIDTH: scaler = aBoundingMetrics.width; break; case NS_MATHML_PSEUDO_UNIT_HEIGHT: scaler = aBoundingMetrics.ascent; break; case NS_MATHML_PSEUDO_UNIT_DEPTH: scaler = aBoundingMetrics.descent; break; case NS_MATHML_PSEUDO_UNIT_LSPACE: scaler = aLeftSpace; break; default: // if we ever reach here, it would mean something is wrong // somewhere with the setup and/or the caller NS_ASSERTION(0, "Unexpected Pseudo Unit"); return; } } if (eCSSUnit_Number == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetFloatValue()); else if (eCSSUnit_Percent == unit) amount = NSToCoordRound(float(scaler) * aCSSValue.GetPercentValue()); else amount = CalcLength(PresContext(), mStyleContext, aCSSValue); nscoord oldValue = aValueToUpdate; if (NS_MATHML_SIGN_PLUS == aSign) aValueToUpdate += amount; else if (NS_MATHML_SIGN_MINUS == aSign) aValueToUpdate -= amount; else aValueToUpdate = amount; /* The REC says: Dimensions that would be positive if the content was rendered normally cannot be made negative using <mpadded>; a positive dimension is set to 0 if it would otherwise become negative. Dimensions which are initially 0 can be made negative */ if (0 < oldValue && 0 > aValueToUpdate) aValueToUpdate = 0; } }
// parse an input string in the following format (see bug 148326 for testcases): // [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | css-unit | namedspace) PRBool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString, PRInt32& aSign, nsCSSValue& aCSSValue, PRInt32& aPseudoUnit) { aCSSValue.Reset(); aSign = NS_MATHML_SIGN_INVALID; aPseudoUnit = NS_MATHML_PSEUDO_UNIT_UNSPECIFIED; aString.CompressWhitespace(); // aString is not a const in this code PRInt32 stringLength = aString.Length(); if (!stringLength) return PR_FALSE; nsAutoString number, unit; ////////////////////// // see if the sign is there PRInt32 i = 0; if (aString[0] == '+') { aSign = NS_MATHML_SIGN_PLUS; i++; } else if (aString[0] == '-') { aSign = NS_MATHML_SIGN_MINUS; i++; } else aSign = NS_MATHML_SIGN_UNSPECIFIED; // skip any space after the sign if (i < stringLength && nsCRT::IsAsciiSpace(aString[i])) i++; // get the number PRBool gotDot = PR_FALSE, gotPercent = PR_FALSE; for (; i < stringLength; i++) { PRUnichar c = aString[i]; if (gotDot && c == '.') { // error - two dots encountered aSign = NS_MATHML_SIGN_INVALID; return PR_FALSE; } if (c == '.') gotDot = PR_TRUE; else if (!nsCRT::IsAsciiDigit(c)) { break; } number.Append(c); } // catch error if we didn't enter the loop above... we could simply initialize // floatValue = 1, to cater for cases such as width="height", but that wouldn't // be in line with the spec which requires an explicit number if (number.IsEmpty()) { #ifdef NS_DEBUG printf("mpadded: attribute with bad numeric value: %s\n", NS_LossyConvertUTF16toASCII(aString).get()); #endif aSign = NS_MATHML_SIGN_INVALID; return PR_FALSE; } PRInt32 errorCode; float floatValue = number.ToFloat(&errorCode); if (errorCode) { aSign = NS_MATHML_SIGN_INVALID; return PR_FALSE; } // skip any space after the number if (i < stringLength && nsCRT::IsAsciiSpace(aString[i])) i++; // see if this is a percentage-based value if (i < stringLength && aString[i] == '%') { i++; gotPercent = PR_TRUE; // skip any space after the '%' sign if (i < stringLength && nsCRT::IsAsciiSpace(aString[i])) i++; } // the remainder now should be a css-unit, or a pseudo-unit, or a named-space aString.Right(unit, stringLength - i); if (unit.IsEmpty()) { // also cater for the edge case of "0" for which the unit is optional if (gotPercent || !floatValue) { aCSSValue.SetPercentValue(floatValue / 100.0f); aPseudoUnit = NS_MATHML_PSEUDO_UNIT_ITSELF; return PR_TRUE; } /* else { // no explicit CSS unit and no explicit pseudo-unit... // In this case, the MathML REC suggests taking ems for // h-unit (width, lspace) or exs for v-unit (height, depth). // Here, however, we explicitly request authors to specify // the unit. This is more in line with the CSS REC (and // it allows keeping the code simpler...) } */ } else if (unit.EqualsLiteral("width")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_WIDTH; else if (unit.EqualsLiteral("height")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_HEIGHT; else if (unit.EqualsLiteral("depth")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_DEPTH; else if (unit.EqualsLiteral("lspace")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_LSPACE; else if (!gotPercent) { // percentage can only apply to a pseudo-unit // see if the unit is a named-space // XXX nsnull in ParseNamedSpacedValue()? don't access mstyle? if (ParseNamedSpaceValue(nsnull, unit, aCSSValue)) { // re-scale properly, and we know that the unit of the named-space is 'em' floatValue *= aCSSValue.GetFloatValue(); aCSSValue.SetFloatValue(floatValue, eCSSUnit_EM); aPseudoUnit = NS_MATHML_PSEUDO_UNIT_NAMEDSPACE; return PR_TRUE; } // see if the input was just a CSS value number.Append(unit); // leave the sign out if it was there if (ParseNumericValue(number, aCSSValue)) return PR_TRUE; } // if we enter here, we have a number that will act as a multiplier on a pseudo-unit if (aPseudoUnit != NS_MATHML_PSEUDO_UNIT_UNSPECIFIED) { if (gotPercent) aCSSValue.SetPercentValue(floatValue / 100.0f); else aCSSValue.SetFloatValue(floatValue, eCSSUnit_Number); return PR_TRUE; } #ifdef NS_DEBUG printf("mpadded: attribute with bad numeric value: %s\n", NS_LossyConvertUTF16toASCII(aString).get()); #endif // if we reach here, it means we encounter an unexpected input aSign = NS_MATHML_SIGN_INVALID; return PR_FALSE; }
/* static */ PRBool nsMathMLFrame::ParseNamedSpaceValue(nsIFrame* aMathMLmstyleFrame, nsString& aString, nsCSSValue& aCSSValue) { aCSSValue.Reset(); aString.CompressWhitespace(); // aString is not a const in this code... if (!aString.Length()) return PR_FALSE; // See if it is one of the 'namedspace' (ranging 1/18em...7/18em) PRInt32 i = 0; nsIAtom* namedspaceAtom = nsnull; if (aString.EqualsLiteral("veryverythinmathspace")) { i = 1; namedspaceAtom = nsMathMLAtoms::veryverythinmathspace_; } else if (aString.EqualsLiteral("verythinmathspace")) { i = 2; namedspaceAtom = nsMathMLAtoms::verythinmathspace_; } else if (aString.EqualsLiteral("thinmathspace")) { i = 3; namedspaceAtom = nsMathMLAtoms::thinmathspace_; } else if (aString.EqualsLiteral("mediummathspace")) { i = 4; namedspaceAtom = nsMathMLAtoms::mediummathspace_; } else if (aString.EqualsLiteral("thickmathspace")) { i = 5; namedspaceAtom = nsMathMLAtoms::thickmathspace_; } else if (aString.EqualsLiteral("verythickmathspace")) { i = 6; namedspaceAtom = nsMathMLAtoms::verythickmathspace_; } else if (aString.EqualsLiteral("veryverythickmathspace")) { i = 7; namedspaceAtom = nsMathMLAtoms::veryverythickmathspace_; } if (0 != i) { if (aMathMLmstyleFrame) { // see if there is a <mstyle> that has overriden the default value // GetAttribute() will recurse all the way up into the <mstyle> hierarchy nsAutoString value; if (NS_CONTENT_ATTR_HAS_VALUE == GetAttribute(nsnull, aMathMLmstyleFrame, namedspaceAtom, value)) { if (ParseNumericValue(value, aCSSValue) && aCSSValue.IsLengthUnit()) { return PR_TRUE; } } } // fall back to the default value aCSSValue.SetFloatValue(float(i)/float(18), eCSSUnit_EM); return PR_TRUE; } return PR_FALSE; }
/** * Tries to call |nsCSSValue::StartImageLoad()| on an image source. * Image sources are specified by |url()| or |-moz-image-rect()| function. */ static void TryToStartImageLoadOnValue(const nsCSSValue& aValue, nsIDocument* aDocument, nsStyleContext* aContext, nsCSSPropertyID aProperty, bool aForTokenStream) { MOZ_ASSERT(aDocument); if (aValue.GetUnit() == eCSSUnit_URL) { #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND // The 'mask-image' property accepts local reference URIs. // For example, // mask-image: url(#mask_id); // refer to a SVG mask element, whose id is // // "mask_id", in the current document. // For such 'mask-image' values (pointing to an in-document element), // there is no need to trigger image download. if (aProperty == eCSSProperty_mask_image) { // Filter out all fragment URLs. // Since nsCSSValue::GetURLStructValue runs much faster than // nsIURI::EqualsExceptRef bellow, we get performance gain by this // early return. URLValue* urlValue = aValue.GetURLStructValue(); if (urlValue->GetLocalURLFlag()) { return; } // Even though urlValue is not a fragment URL, it might still refer to // an internal resource. // For example, aDocument base URL is "http://foo/index.html" and // intentionally references a mask-image at // url(http://foo/index.html#mask) which still refers to a resource in // aDocument. nsIURI* imageURI = aValue.GetURLValue(); if (imageURI) { nsIURI* docURI = aDocument->GetDocumentURI(); bool isEqualExceptRef = false; nsresult rv = imageURI->EqualsExceptRef(docURI, &isEqualExceptRef); if (NS_SUCCEEDED(rv) && isEqualExceptRef) { return; } } } #endif aValue.StartImageLoad(aDocument); if (aForTokenStream && aContext) { CSSVariableImageTable::Add(aContext, aProperty, aValue.GetImageStructValue()); } } else if (aValue.GetUnit() == eCSSUnit_Image) { // If we already have a request, see if this document needs to clone it. imgIRequest* request = aValue.GetImageValue(nullptr); if (request) { ImageValue* imageValue = aValue.GetImageStructValue(); aDocument->StyleImageLoader()->MaybeRegisterCSSImage(imageValue); if (aForTokenStream && aContext) { CSSVariableImageTable::Add(aContext, aProperty, imageValue); } } } else if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) { nsCSSValue::Array* arguments = aValue.GetArrayValue(); MOZ_ASSERT(arguments->Count() == 6, "unexpected num of arguments"); const nsCSSValue& image = arguments->Item(1); TryToStartImageLoadOnValue(image, aDocument, aContext, aProperty, aForTokenStream); } }
static void GetIsGlyph(nsPresContext* aPresContext, const nsMediaFeature* aFeature, nsCSSValue& aResult) { aResult.SetIntValue(aPresContext->IsGlyph() ? 1 : 0, eCSSUnit_Integer); }
// parse an input string in the following format (see bug 148326 for testcases): // [+|-] unsigned-number (% [pseudo-unit] | pseudo-unit | css-unit | namedspace) bool nsMathMLmpaddedFrame::ParseAttribute(nsString& aString, int32_t& aSign, nsCSSValue& aCSSValue, int32_t& aPseudoUnit) { aCSSValue.Reset(); aSign = NS_MATHML_SIGN_INVALID; aPseudoUnit = NS_MATHML_PSEUDO_UNIT_UNSPECIFIED; aString.CompressWhitespace(); // aString is not a const in this code int32_t stringLength = aString.Length(); if (!stringLength) return false; nsAutoString number, unit; ////////////////////// // see if the sign is there int32_t i = 0; if (aString[0] == '+') { aSign = NS_MATHML_SIGN_PLUS; i++; } else if (aString[0] == '-') { aSign = NS_MATHML_SIGN_MINUS; i++; } else aSign = NS_MATHML_SIGN_UNSPECIFIED; // get the number bool gotDot = false, gotPercent = false; for (; i < stringLength; i++) { PRUnichar c = aString[i]; if (gotDot && c == '.') { // error - two dots encountered aSign = NS_MATHML_SIGN_INVALID; return false; } if (c == '.') gotDot = true; else if (!nsCRT::IsAsciiDigit(c)) { break; } number.Append(c); } // catch error if we didn't enter the loop above... we could simply initialize // floatValue = 1, to cater for cases such as width="height", but that wouldn't // be in line with the spec which requires an explicit number if (number.IsEmpty()) { aSign = NS_MATHML_SIGN_INVALID; return false; } nsresult errorCode; float floatValue = number.ToFloat(&errorCode); if (NS_FAILED(errorCode)) { aSign = NS_MATHML_SIGN_INVALID; return false; } // see if this is a percentage-based value if (i < stringLength && aString[i] == '%') { i++; gotPercent = true; } // the remainder now should be a css-unit, or a pseudo-unit, or a named-space aString.Right(unit, stringLength - i); if (unit.IsEmpty()) { if (gotPercent) { // case ["+"|"-"] unsigned-number "%" aCSSValue.SetPercentValue(floatValue / 100.0f); aPseudoUnit = NS_MATHML_PSEUDO_UNIT_ITSELF; return true; } else { // case ["+"|"-"] unsigned-number // XXXfredw: should we allow non-zero unitless values? See bug 757703. if (!floatValue) { aCSSValue.SetFloatValue(floatValue, eCSSUnit_Number); aPseudoUnit = NS_MATHML_PSEUDO_UNIT_ITSELF; return true; } } } else if (unit.EqualsLiteral("width")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_WIDTH; else if (unit.EqualsLiteral("height")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_HEIGHT; else if (unit.EqualsLiteral("depth")) aPseudoUnit = NS_MATHML_PSEUDO_UNIT_DEPTH; else if (!gotPercent) { // percentage can only apply to a pseudo-unit // see if the unit is a named-space if (nsMathMLElement::ParseNamedSpaceValue(unit, aCSSValue, nsMathMLElement:: PARSE_ALLOW_NEGATIVE)) { // re-scale properly, and we know that the unit of the named-space is 'em' floatValue *= aCSSValue.GetFloatValue(); aCSSValue.SetFloatValue(floatValue, eCSSUnit_EM); aPseudoUnit = NS_MATHML_PSEUDO_UNIT_NAMEDSPACE; return true; } // see if the input was just a CSS value // We are not supposed to have a unitless, percent, negative or namedspace // value here. number.Append(unit); // leave the sign out if it was there if (nsMathMLElement::ParseNumericValue(number, aCSSValue, nsMathMLElement:: PARSE_SUPPRESS_WARNINGS, nullptr)) return true; } // if we enter here, we have a number that will act as a multiplier on a pseudo-unit if (aPseudoUnit != NS_MATHML_PSEUDO_UNIT_UNSPECIFIED) { if (gotPercent) aCSSValue.SetPercentValue(floatValue / 100.0f); else aCSSValue.SetFloatValue(floatValue, eCSSUnit_Number); return true; } #ifdef DEBUG printf("mpadded: attribute with bad numeric value: %s\n", NS_LossyConvertUTF16toASCII(aString).get()); #endif // if we reach here, it means we encounter an unexpected input aSign = NS_MATHML_SIGN_INVALID; return false; }
/* static */ PRBool nsMathMLFrame::ParseNumericValue(nsString& aString, nsCSSValue& aCSSValue) { aCSSValue.Reset(); aString.CompressWhitespace(); // aString is not a const in this code... PRInt32 stringLength = aString.Length(); if (!stringLength) return PR_FALSE; nsAutoString number, unit; // Gather up characters that make up the number PRBool gotDot = PR_FALSE; PRUnichar c; for (PRInt32 i = 0; i < stringLength; i++) { c = aString[i]; if (gotDot && c == '.') return PR_FALSE; // two dots encountered else if (c == '.') gotDot = PR_TRUE; else if (!nsCRT::IsAsciiDigit(c)) { aString.Right(unit, stringLength - i); unit.CompressWhitespace(); // some authors leave blanks before the unit break; } number.Append(c); } // on exit, also return a nicer string version of the value in case // the caller wants it (e.g., this removes whitespace before units) aString.Assign(number); aString.Append(unit); // Convert number to floating point PRInt32 errorCode; float floatValue = number.ToFloat(&errorCode); if (errorCode) return PR_FALSE; nsCSSUnit cssUnit; if (unit.IsEmpty()) { cssUnit = eCSSUnit_Number; // no explicit unit, this is a number that will act as a multiplier } else if (unit.EqualsLiteral("%")) { aCSSValue.SetPercentValue(floatValue / 100.0f); return PR_TRUE; } else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM; else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight; else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel; else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch; else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter; else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter; else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point; else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica; else // unexpected unit return PR_FALSE; aCSSValue.SetFloatValue(floatValue, cssUnit); return PR_TRUE; }
/* static */ PRBool nsMathMLElement::ParseNumericValue(const nsString& aString, nsCSSValue& aCSSValue, PRUint32 aFlags) { nsAutoString str(aString); str.CompressWhitespace(); // aString is const in this code... PRInt32 stringLength = str.Length(); if (!stringLength) return PR_FALSE; nsAutoString number, unit; // see if the negative sign is there PRInt32 i = 0; PRUnichar c = str[0]; if (c == '-') { number.Append(c); i++; // skip any space after the negative sign if (i < stringLength && nsCRT::IsAsciiSpace(str[i])) i++; } // Gather up characters that make up the number PRBool gotDot = PR_FALSE; for ( ; i < stringLength; i++) { c = str[i]; if (gotDot && c == '.') return PR_FALSE; // two dots encountered else if (c == '.') gotDot = PR_TRUE; else if (!nsCRT::IsAsciiDigit(c)) { str.Right(unit, stringLength - i); // some authors leave blanks before the unit, but that shouldn't // be allowed, so don't CompressWhitespace on 'unit'. break; } number.Append(c); } // Convert number to floating point PRInt32 errorCode; float floatValue = number.ToFloat(&errorCode); if (NS_FAILED(errorCode)) return PR_FALSE; if (floatValue < 0 && !(aFlags & PARSE_ALLOW_NEGATIVE)) return PR_FALSE; nsCSSUnit cssUnit; if (unit.IsEmpty()) { if (aFlags & PARSE_ALLOW_UNITLESS) { // no explicit unit, this is a number that will act as a multiplier cssUnit = eCSSUnit_Number; } else { // We are supposed to have a unit, but there isn't one. // If the value is 0 we can just call it "pixels" otherwise // this is illegal. if (floatValue != 0.0) return PR_FALSE; cssUnit = eCSSUnit_Pixel; } } else if (unit.EqualsLiteral("%")) { aCSSValue.SetPercentValue(floatValue / 100.0f); return PR_TRUE; } else if (unit.EqualsLiteral("em")) cssUnit = eCSSUnit_EM; else if (unit.EqualsLiteral("ex")) cssUnit = eCSSUnit_XHeight; else if (unit.EqualsLiteral("px")) cssUnit = eCSSUnit_Pixel; else if (unit.EqualsLiteral("in")) cssUnit = eCSSUnit_Inch; else if (unit.EqualsLiteral("cm")) cssUnit = eCSSUnit_Centimeter; else if (unit.EqualsLiteral("mm")) cssUnit = eCSSUnit_Millimeter; else if (unit.EqualsLiteral("pt")) cssUnit = eCSSUnit_Point; else if (unit.EqualsLiteral("pc")) cssUnit = eCSSUnit_Pica; else // unexpected unit return PR_FALSE; aCSSValue.SetFloatValue(floatValue, cssUnit); return PR_TRUE; }
static void GetIsResourceDocument(nsIDocument* aDocument, const nsMediaFeature*, nsCSSValue& aResult) { aResult.SetIntValue(aDocument->IsResourceDoc() ? 1 : 0, eCSSUnit_Integer); }