mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 20:49:27 +00:00
Implement Media Queries. (Bug 156716) r+sr=bzbarsky
This commit is contained in:
parent
0169af2ccf
commit
62b65d2845
@ -104,6 +104,7 @@ GK_ATOM(applyTemplates, "apply-templates")
|
||||
GK_ATOM(archive, "archive")
|
||||
GK_ATOM(area, "area")
|
||||
GK_ATOM(ascending, "ascending")
|
||||
GK_ATOM(aspectRatio, "aspect-ratio")
|
||||
GK_ATOM(assign, "assign")
|
||||
GK_ATOM(attribute, "attribute")
|
||||
GK_ATOM(attributeSet, "attribute-set")
|
||||
@ -202,6 +203,7 @@ GK_ATOM(colGroupList, "ColGroup-list")
|
||||
GK_ATOM(collapse, "collapse")
|
||||
GK_ATOM(collapsed, "collapsed")
|
||||
GK_ATOM(color, "color")
|
||||
GK_ATOM(colorIndex, "color-index")
|
||||
GK_ATOM(cols, "cols")
|
||||
GK_ATOM(colspan, "colspan")
|
||||
GK_ATOM(column, "column")
|
||||
@ -272,6 +274,9 @@ GK_ATOM(descendantOrSelf, "descendant-or-self")
|
||||
GK_ATOM(descending, "descending")
|
||||
GK_ATOM(description, "description")
|
||||
GK_ATOM(destructor, "destructor")
|
||||
GK_ATOM(deviceAspectRatio, "device-aspect-ratio")
|
||||
GK_ATOM(deviceHeight, "device-height")
|
||||
GK_ATOM(deviceWidth, "device-width")
|
||||
GK_ATOM(dfn, "dfn")
|
||||
GK_ATOM(dialog, "dialog")
|
||||
GK_ATOM(difference, "difference")
|
||||
@ -523,6 +528,7 @@ GK_ATOM(minwidth, "minwidth")
|
||||
GK_ATOM(mod, "mod")
|
||||
GK_ATOM(mode, "mode")
|
||||
GK_ATOM(modifiers, "modifiers")
|
||||
GK_ATOM(monochrome, "monochrome")
|
||||
GK_ATOM(mousedown, "mousedown")
|
||||
GK_ATOM(mousemove, "mousemove")
|
||||
GK_ATOM(mouseout, "mouseout")
|
||||
@ -616,6 +622,7 @@ GK_ATOM(onkeypress, "onkeypress")
|
||||
GK_ATOM(onkeyup, "onkeyup")
|
||||
GK_ATOM(onLoad, "onLoad")
|
||||
GK_ATOM(onload, "onload")
|
||||
GK_ATOM(only, "only") // this one is not an event
|
||||
GK_ATOM(onmousedown, "onmousedown")
|
||||
GK_ATOM(onmousemove, "onmousemove")
|
||||
GK_ATOM(onmouseout, "onmouseout")
|
||||
@ -650,6 +657,7 @@ GK_ATOM(_or, "or")
|
||||
GK_ATOM(order, "order")
|
||||
GK_ATOM(ordinal, "ordinal")
|
||||
GK_ATOM(orient, "orient")
|
||||
GK_ATOM(orientation, "orientation")
|
||||
GK_ATOM(otherwise, "otherwise")
|
||||
GK_ATOM(output, "output")
|
||||
GK_ATOM(overflow, "overflow")
|
||||
@ -739,6 +747,7 @@ GK_ATOM(reset, "reset")
|
||||
GK_ATOM(resizeafter, "resizeafter")
|
||||
GK_ATOM(resizebefore, "resizebefore")
|
||||
GK_ATOM(resizer, "resizer")
|
||||
GK_ATOM(resolution, "resolution")
|
||||
GK_ATOM(resource, "resource")
|
||||
GK_ATOM(resources, "resources")
|
||||
GK_ATOM(result, "result")
|
||||
@ -758,6 +767,7 @@ GK_ATOM(rule, "rule")
|
||||
GK_ATOM(rules, "rules")
|
||||
GK_ATOM(s, "s")
|
||||
GK_ATOM(samp, "samp")
|
||||
GK_ATOM(scan, "scan")
|
||||
GK_ATOM(scheme, "scheme")
|
||||
GK_ATOM(scope, "scope")
|
||||
GK_ATOM(screen, "screen")
|
||||
|
@ -127,3 +127,8 @@ PEBadDeclOrRuleEnd2=Expected ';' or '}' to terminate declaration but found '%1$S
|
||||
PEInaccessibleProperty2=Cannot specify value for internal property.
|
||||
PECommentEOF=end of comment
|
||||
SEUnterminatedString=Found unclosed string '%1$S'.
|
||||
PEMQExpectedExpressionStart=Expected '(' to start media query expression but found '%1$S'.
|
||||
PEMQExpressionEOF=contents of media query expression
|
||||
PEMQExpectedFeatureName=Expected media feature name but found '%1$S'.
|
||||
PEMQExpectedFeatureNameEnd=Expected ':' or ')' after media feature name but found '%1$S'.
|
||||
PEMQExpectedFeatureValue=Found invalid value for media feature.
|
||||
|
@ -746,4 +746,16 @@
|
||||
|
||||
#endif // MOZ_SVG
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants for media features. *
|
||||
*****************************************************************************/
|
||||
|
||||
// orientation
|
||||
#define NS_STYLE_ORIENTATION_PORTRAIT 0
|
||||
#define NS_STYLE_ORIENTATION_LANDSCAPE 1
|
||||
|
||||
// scan
|
||||
#define NS_STYLE_SCAN_PROGRESSIVE 0
|
||||
#define NS_STYLE_SCAN_INTERLACE 1
|
||||
|
||||
#endif /* nsStyleConsts_h___ */
|
||||
|
@ -151,6 +151,7 @@ CPPSRCS = \
|
||||
nsHTMLStyleSheet.cpp \
|
||||
nsInspectorCSSUtils.cpp \
|
||||
nsLayoutStylesheetCache.cpp \
|
||||
nsMediaFeatures.cpp \
|
||||
nsROCSSPrimitiveValue.cpp \
|
||||
nsRuleNode.cpp \
|
||||
nsStyleContext.cpp \
|
||||
|
@ -158,11 +158,13 @@ private:
|
||||
static void AppendImportanceToString(PRBool aIsImportant, nsAString& aString);
|
||||
// return whether there was a value in |aValue| (i.e., it had a non-null unit)
|
||||
PRBool AppendValueToString(nsCSSProperty aProperty, nsAString& aResult) const;
|
||||
public:
|
||||
// return whether there was a value in |aValue| (i.e., it had a non-null unit)
|
||||
static PRBool AppendCSSValueToString(nsCSSProperty aProperty,
|
||||
const nsCSSValue& aValue,
|
||||
nsAString& aResult);
|
||||
|
||||
private:
|
||||
// May be called only for properties whose type is eCSSType_Value.
|
||||
nsresult GetValueOrImportantValue(nsCSSProperty aProperty, nsCSSValue& aValue) const;
|
||||
|
||||
|
@ -293,6 +293,7 @@ CSS_KEY(hz, hz)
|
||||
CSS_KEY(icon, icon)
|
||||
CSS_KEY(ignore, ignore)
|
||||
CSS_KEY(in, in)
|
||||
CSS_KEY(interlace, interlace)
|
||||
CSS_KEY(inactive, inactive)
|
||||
CSS_KEY(inactiveborder, inactiveborder)
|
||||
CSS_KEY(inactivecaption, inactivecaption)
|
||||
@ -374,6 +375,7 @@ CSS_KEY(portrait, portrait)
|
||||
CSS_KEY(pre, pre)
|
||||
CSS_KEY(pre-wrap, pre_wrap)
|
||||
CSS_KEY(progress, progress)
|
||||
CSS_KEY(progressive, progressive)
|
||||
CSS_KEY(pt, pt)
|
||||
CSS_KEY(px, px)
|
||||
CSS_KEY(rad, rad)
|
||||
|
@ -84,6 +84,62 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
// Flags for ParseVariant method
|
||||
#define VARIANT_KEYWORD 0x000001 // K
|
||||
#define VARIANT_LENGTH 0x000002 // L
|
||||
#define VARIANT_PERCENT 0x000004 // P
|
||||
#define VARIANT_COLOR 0x000008 // C eCSSUnit_Color, eCSSUnit_String (e.g. "red")
|
||||
#define VARIANT_URL 0x000010 // U
|
||||
#define VARIANT_NUMBER 0x000020 // N
|
||||
#define VARIANT_INTEGER 0x000040 // I
|
||||
#define VARIANT_ANGLE 0x000080 // G
|
||||
#define VARIANT_FREQUENCY 0x000100 // F
|
||||
#define VARIANT_TIME 0x000200 // T
|
||||
#define VARIANT_STRING 0x000400 // S
|
||||
#define VARIANT_COUNTER 0x000800 //
|
||||
#define VARIANT_ATTR 0x001000 //
|
||||
#define VARIANT_IDENTIFIER 0x002000 // D
|
||||
#define VARIANT_AUTO 0x010000 // A
|
||||
#define VARIANT_INHERIT 0x020000 // H eCSSUnit_Initial, eCSSUnit_Inherit
|
||||
#define VARIANT_NONE 0x040000 // O
|
||||
#define VARIANT_NORMAL 0x080000 // M
|
||||
#define VARIANT_SYSFONT 0x100000 // eCSSUnit_System_Font
|
||||
|
||||
// Common combinations of variants
|
||||
#define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH)
|
||||
#define VARIANT_LP (VARIANT_LENGTH | VARIANT_PERCENT)
|
||||
#define VARIANT_AH (VARIANT_AUTO | VARIANT_INHERIT)
|
||||
#define VARIANT_AHLP (VARIANT_AH | VARIANT_LP)
|
||||
#define VARIANT_AHI (VARIANT_AH | VARIANT_INTEGER)
|
||||
#define VARIANT_AHK (VARIANT_AH | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHKLP (VARIANT_AHLP | VARIANT_KEYWORD)
|
||||
#define VARIANT_AUK (VARIANT_AUTO | VARIANT_URL | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHUK (VARIANT_AH | VARIANT_URL | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHL (VARIANT_AH | VARIANT_LENGTH)
|
||||
#define VARIANT_AHKL (VARIANT_AHK | VARIANT_LENGTH)
|
||||
#define VARIANT_HK (VARIANT_INHERIT | VARIANT_KEYWORD)
|
||||
#define VARIANT_HKF (VARIANT_HK | VARIANT_FREQUENCY)
|
||||
#define VARIANT_HKL (VARIANT_HK | VARIANT_LENGTH)
|
||||
#define VARIANT_HKLP (VARIANT_HK | VARIANT_LP)
|
||||
#define VARIANT_HKLPO (VARIANT_HKLP | VARIANT_NONE)
|
||||
#define VARIANT_HL (VARIANT_INHERIT | VARIANT_LENGTH)
|
||||
#define VARIANT_HI (VARIANT_INHERIT | VARIANT_INTEGER)
|
||||
#define VARIANT_HLP (VARIANT_HL | VARIANT_PERCENT)
|
||||
#define VARIANT_HLPN (VARIANT_HLP | VARIANT_NUMBER)
|
||||
#define VARIANT_HLPO (VARIANT_HLP | VARIANT_NONE)
|
||||
#define VARIANT_HTP (VARIANT_INHERIT | VARIANT_TIME | VARIANT_PERCENT)
|
||||
#define VARIANT_HMK (VARIANT_HK | VARIANT_NORMAL)
|
||||
#define VARIANT_HMKI (VARIANT_HMK | VARIANT_INTEGER)
|
||||
#define VARIANT_HC (VARIANT_INHERIT | VARIANT_COLOR)
|
||||
#define VARIANT_HCK (VARIANT_HK | VARIANT_COLOR)
|
||||
#define VARIANT_HUO (VARIANT_INHERIT | VARIANT_URL | VARIANT_NONE)
|
||||
#define VARIANT_AHUO (VARIANT_AUTO | VARIANT_HUO)
|
||||
#define VARIANT_HPN (VARIANT_INHERIT | VARIANT_PERCENT | VARIANT_NUMBER)
|
||||
#define VARIANT_HOK (VARIANT_HK | VARIANT_NONE)
|
||||
#define VARIANT_HN (VARIANT_INHERIT | VARIANT_NUMBER)
|
||||
#define VARIANT_HON (VARIANT_HN | VARIANT_NONE)
|
||||
#define VARIANT_HOS (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Your basic top-down recursive descent style parser
|
||||
@ -227,8 +283,10 @@ protected:
|
||||
PRBool ParseCharsetRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
PRBool ParseImportRule(nsresult& aErrorCode, RuleAppendFunc aAppendFunc, void* aProcessData);
|
||||
PRBool GatherURL(nsresult& aErrorCode, nsString& aURL);
|
||||
// Callers must clear or throw out aMedia if GatherMedia returns false.
|
||||
PRBool GatherMedia(nsresult& aErrorCode, nsMediaList* aMedia,
|
||||
PRUnichar aStopSymbol);
|
||||
PRBool ParseMediaQueryExpression(nsresult& aErrorCode, nsMediaQuery* aQuery);
|
||||
PRBool ProcessImport(nsresult& aErrorCode,
|
||||
const nsString& aURLSpec,
|
||||
nsMediaList* aMedia,
|
||||
@ -1051,6 +1109,8 @@ CSSParserImpl::ParseMediaList(const nsSubstring& aBuffer,
|
||||
nsMediaList* aMediaList,
|
||||
PRBool aHTMLMode)
|
||||
{
|
||||
// XXX Are there cases where the caller wants to keep what it already
|
||||
// has in case of parser error?
|
||||
aMediaList->Clear();
|
||||
|
||||
AssertInitialState();
|
||||
@ -1094,8 +1154,12 @@ CSSParserImpl::DoParseMediaList(const nsSubstring& aBuffer,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!GatherMedia(rv, aMediaList, PRUnichar(0)) && !mHTMLMediaMode) {
|
||||
OUTPUT_ERROR();
|
||||
if (!GatherMedia(rv, aMediaList, PRUnichar(0))) {
|
||||
aMediaList->Clear();
|
||||
aMediaList->SetNonEmpty(); // don't match anything
|
||||
if (!mHTMLMediaMode) {
|
||||
OUTPUT_ERROR();
|
||||
}
|
||||
}
|
||||
CLEAR_ERROR();
|
||||
ReleaseScanner();
|
||||
@ -1417,50 +1481,261 @@ PRBool CSSParserImpl::GatherURL(nsresult& aErrorCode, nsString& aURL)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Callers must clear or throw out aMedia if GatherMedia returns false.
|
||||
PRBool CSSParserImpl::GatherMedia(nsresult& aErrorCode,
|
||||
nsMediaList* aMedia,
|
||||
PRUnichar aStopSymbol)
|
||||
{
|
||||
for (;;) {
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
break;
|
||||
}
|
||||
if (eCSSToken_Ident != mToken.mType) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotIdent);
|
||||
UngetToken();
|
||||
break;
|
||||
}
|
||||
ToLowerCase(mToken.mIdent); // case insensitive from CSS - must be lower cased
|
||||
nsCOMPtr<nsIAtom> medium = do_GetAtom(mToken.mIdent);
|
||||
aMedia->AppendAtom(medium);
|
||||
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
// expected termination by EOF
|
||||
if (aStopSymbol == PRUnichar(0))
|
||||
return PR_TRUE;
|
||||
|
||||
// unexpected termination by EOF; if we were looking for a
|
||||
// semicolon, return true anyway, for the same reason this is
|
||||
// done by ExpectSymbol().
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
if (aStopSymbol == PRUnichar(';'))
|
||||
return PR_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (eCSSToken_Symbol == mToken.mType &&
|
||||
mToken.mSymbol == aStopSymbol) {
|
||||
UngetToken();
|
||||
// "If the comma-separated list is the empty list it is assumed to
|
||||
// specify the media query 'all'." (css3-mediaqueries, section
|
||||
// "Media Queries")
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
// expected termination by EOF
|
||||
if (aStopSymbol == PRUnichar(0))
|
||||
return PR_TRUE;
|
||||
} else if (eCSSToken_Symbol != mToken.mType ||
|
||||
mToken.mSymbol != ',') {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotComma);
|
||||
UngetToken();
|
||||
|
||||
// unexpected termination by EOF; if we were looking for a
|
||||
// semicolon, return true anyway, for the same reason this is
|
||||
// done by ExpectSymbol().
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
return aStopSymbol == PRUnichar(';');
|
||||
}
|
||||
|
||||
if (eCSSToken_Symbol == mToken.mType &&
|
||||
mToken.mSymbol == aStopSymbol) {
|
||||
UngetToken();
|
||||
return PR_TRUE;
|
||||
}
|
||||
UngetToken();
|
||||
aMedia->SetNonEmpty();
|
||||
|
||||
for (;;) {
|
||||
// We want to still have |query| after we transfer ownership from
|
||||
// |queryHolder| to |aMedia|.
|
||||
nsMediaQuery *query;
|
||||
{
|
||||
nsAutoPtr<nsMediaQuery> queryHolder(new nsMediaQuery);
|
||||
if (!queryHolder) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
return PR_FALSE;
|
||||
}
|
||||
query = queryHolder;
|
||||
|
||||
// In terms of error handling, it doesn't really matter when we
|
||||
// append this, since aMedia's contents get dropped entirely
|
||||
// whenever there is an error.
|
||||
nsresult rv = aMedia->AppendQuery(queryHolder);
|
||||
if (NS_FAILED(rv)) {
|
||||
aErrorCode = rv;
|
||||
return PR_FALSE;
|
||||
}
|
||||
NS_ASSERTION(!queryHolder, "ownership should have been transferred");
|
||||
}
|
||||
|
||||
if (ExpectSymbol(aErrorCode, '(', PR_TRUE)) {
|
||||
// we got an expression without a media type
|
||||
UngetToken(); // so ParseMediaQueryExpression can handle it
|
||||
query->SetType(nsGkAtoms::all);
|
||||
query->SetTypeOmitted();
|
||||
// Just parse the first expression here.
|
||||
if (!ParseMediaQueryExpression(aErrorCode, query)) {
|
||||
OUTPUT_ERROR();
|
||||
query->SetHadUnknownExpression();
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIAtom> mediaType;
|
||||
PRBool gotNotOrOnly = PR_FALSE;
|
||||
for (;;) {
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (eCSSToken_Ident != mToken.mType) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotIdent);
|
||||
UngetToken();
|
||||
return PR_FALSE;
|
||||
}
|
||||
// case insensitive from CSS - must be lower cased
|
||||
ToLowerCase(mToken.mIdent);
|
||||
mediaType = do_GetAtom(mToken.mIdent);
|
||||
if (gotNotOrOnly ||
|
||||
(mediaType != nsGkAtoms::_not && mediaType != nsGkAtoms::only))
|
||||
break;
|
||||
gotNotOrOnly = PR_TRUE;
|
||||
if (mediaType == nsGkAtoms::_not)
|
||||
query->SetNegated();
|
||||
else
|
||||
query->SetHasOnly();
|
||||
}
|
||||
query->SetType(mediaType);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (!GetToken(aErrorCode, PR_TRUE)) {
|
||||
// expected termination by EOF
|
||||
if (aStopSymbol == PRUnichar(0))
|
||||
return PR_TRUE;
|
||||
|
||||
// unexpected termination by EOF; if we were looking for a
|
||||
// semicolon, return true anyway, for the same reason this is
|
||||
// done by ExpectSymbol().
|
||||
REPORT_UNEXPECTED_EOF(PEGatherMediaEOF);
|
||||
return aStopSymbol == PRUnichar(';');
|
||||
}
|
||||
|
||||
if (eCSSToken_Symbol == mToken.mType &&
|
||||
mToken.mSymbol == aStopSymbol) {
|
||||
UngetToken();
|
||||
return PR_TRUE;
|
||||
}
|
||||
if (eCSSToken_Symbol == mToken.mType && mToken.mSymbol == ',') {
|
||||
// Done with the expressions for this query
|
||||
break;
|
||||
}
|
||||
if (eCSSToken_Ident != mToken.mType ||
|
||||
!mToken.mIdent.LowerCaseEqualsLiteral("and")) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEGatherMediaNotComma);
|
||||
UngetToken();
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!ParseMediaQueryExpression(aErrorCode, query)) {
|
||||
OUTPUT_ERROR();
|
||||
query->SetHadUnknownExpression();
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_NOTREACHED("unreachable code");
|
||||
return PR_FALSE; // keep the compiler happy
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseMediaQueryExpression(nsresult& aErrorCode, nsMediaQuery* aQuery)
|
||||
{
|
||||
if (!ExpectSymbol(aErrorCode, '(', PR_TRUE)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedExpressionStart);
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (! GetToken(aErrorCode, PR_TRUE)) {
|
||||
REPORT_UNEXPECTED_EOF(PEMQExpressionEOF);
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (eCSSToken_Ident != mToken.mType) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureName);
|
||||
SkipUntil(aErrorCode, ')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsMediaExpression *expr = aQuery->NewExpression();
|
||||
if (!expr) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
SkipUntil(aErrorCode, ')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// case insensitive from CSS - must be lower cased
|
||||
ToLowerCase(mToken.mIdent);
|
||||
const PRUnichar *featureString;
|
||||
if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("min-"))) {
|
||||
expr->mRange = nsMediaExpression::eMin;
|
||||
featureString = mToken.mIdent.get() + 4;
|
||||
} else if (StringBeginsWith(mToken.mIdent, NS_LITERAL_STRING("max-"))) {
|
||||
expr->mRange = nsMediaExpression::eMax;
|
||||
featureString = mToken.mIdent.get() + 4;
|
||||
} else {
|
||||
expr->mRange = nsMediaExpression::eEqual;
|
||||
featureString = mToken.mIdent.get();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> mediaFeatureAtom = do_GetAtom(featureString);
|
||||
const nsMediaFeature *feature = nsMediaFeatures::features;
|
||||
for (; feature->mName; ++feature) {
|
||||
if (*(feature->mName) == mediaFeatureAtom) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
if (!feature->mName ||
|
||||
(expr->mRange != nsMediaExpression::eEqual &&
|
||||
feature->mRangeType != nsMediaFeature::eMinMaxAllowed)) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureName);
|
||||
SkipUntil(aErrorCode, ')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
expr->mFeature = feature;
|
||||
|
||||
if (! GetToken(aErrorCode, PR_TRUE)) {
|
||||
REPORT_UNEXPECTED_EOF(PEMQExpressionEOF);
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (eCSSToken_Symbol != mToken.mType ||
|
||||
(mToken.mSymbol != PRUnichar(':') && mToken.mSymbol != PRUnichar(')'))) {
|
||||
REPORT_UNEXPECTED_TOKEN(PEMQExpectedFeatureNameEnd);
|
||||
SkipUntil(aErrorCode, ')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (mToken.mSymbol == PRUnichar(')')) {
|
||||
// All query expressions can be given without a value.
|
||||
expr->mValue.Reset();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool rv;
|
||||
switch (feature->mValueType) {
|
||||
case nsMediaFeature::eLength:
|
||||
rv = ParsePositiveVariant(aErrorCode, expr->mValue,
|
||||
VARIANT_LENGTH, nsnull);
|
||||
break;
|
||||
case nsMediaFeature::eInteger:
|
||||
rv = ParsePositiveVariant(aErrorCode, expr->mValue,
|
||||
VARIANT_INTEGER, nsnull);
|
||||
break;
|
||||
case nsMediaFeature::eIntRatio:
|
||||
{
|
||||
// Two integers separated by '/', with optional whitespace on
|
||||
// either side of the '/'.
|
||||
nsRefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
|
||||
if (!a) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
SkipUntil(aErrorCode, ')');
|
||||
return PR_FALSE;
|
||||
}
|
||||
expr->mValue.SetArrayValue(a, eCSSUnit_Array);
|
||||
// We don't bother with ParsePositiveVariant since we have to
|
||||
// check for != 0 as well; no need to worry about the UngetToken
|
||||
// since we're throwing out up to the next ')' anyway.
|
||||
rv = ParseVariant(aErrorCode, a->Item(0), VARIANT_INTEGER, nsnull) &&
|
||||
a->Item(0).GetIntValue() > 0 &&
|
||||
ExpectSymbol(aErrorCode, '/', PR_TRUE) &&
|
||||
ParseVariant(aErrorCode, a->Item(1), VARIANT_INTEGER, nsnull) &&
|
||||
a->Item(1).GetIntValue() > 0;
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eResolution:
|
||||
rv = GetToken(aErrorCode, PR_TRUE) && mToken.IsDimension() &&
|
||||
mToken.mIntegerValid && mToken.mNumber > 0.0f;
|
||||
if (rv) {
|
||||
// No worries about whether unitless zero is allowed, since the
|
||||
// value must be positive (and we checked that above).
|
||||
NS_ASSERTION(!mToken.mIdent.IsEmpty(), "IsDimension lied");
|
||||
if (mToken.mIdent.LowerCaseEqualsLiteral("dpi")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Inch);
|
||||
} else if (mToken.mIdent.LowerCaseEqualsLiteral("dpcm")) {
|
||||
expr->mValue.SetFloatValue(mToken.mNumber, eCSSUnit_Centimeter);
|
||||
} else {
|
||||
rv = PR_FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eEnumerated:
|
||||
rv = ParseVariant(aErrorCode, expr->mValue, VARIANT_KEYWORD,
|
||||
feature->mKeywordTable);
|
||||
break;
|
||||
}
|
||||
if (!rv) {
|
||||
REPORT_UNEXPECTED(PEMQExpectedFeatureValue);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return ExpectSymbol(aErrorCode, ')', PR_TRUE);
|
||||
}
|
||||
|
||||
// Parse a CSS2 import rule: "@import STRING | URL [medium [, medium]]"
|
||||
@ -3696,62 +3971,6 @@ CSSParserImpl::DoTransferTempData(nsCSSDeclaration* aDeclaration,
|
||||
}
|
||||
}
|
||||
|
||||
// Flags for ParseVariant method
|
||||
#define VARIANT_KEYWORD 0x000001 // K
|
||||
#define VARIANT_LENGTH 0x000002 // L
|
||||
#define VARIANT_PERCENT 0x000004 // P
|
||||
#define VARIANT_COLOR 0x000008 // C eCSSUnit_Color, eCSSUnit_String (e.g. "red")
|
||||
#define VARIANT_URL 0x000010 // U
|
||||
#define VARIANT_NUMBER 0x000020 // N
|
||||
#define VARIANT_INTEGER 0x000040 // I
|
||||
#define VARIANT_ANGLE 0x000080 // G
|
||||
#define VARIANT_FREQUENCY 0x000100 // F
|
||||
#define VARIANT_TIME 0x000200 // T
|
||||
#define VARIANT_STRING 0x000400 // S
|
||||
#define VARIANT_COUNTER 0x000800 //
|
||||
#define VARIANT_ATTR 0x001000 //
|
||||
#define VARIANT_IDENTIFIER 0x002000 // D
|
||||
#define VARIANT_AUTO 0x010000 // A
|
||||
#define VARIANT_INHERIT 0x020000 // H eCSSUnit_Initial, eCSSUnit_Inherit
|
||||
#define VARIANT_NONE 0x040000 // O
|
||||
#define VARIANT_NORMAL 0x080000 // M
|
||||
#define VARIANT_SYSFONT 0x100000 // eCSSUnit_System_Font
|
||||
|
||||
// Common combinations of variants
|
||||
#define VARIANT_AL (VARIANT_AUTO | VARIANT_LENGTH)
|
||||
#define VARIANT_LP (VARIANT_LENGTH | VARIANT_PERCENT)
|
||||
#define VARIANT_AH (VARIANT_AUTO | VARIANT_INHERIT)
|
||||
#define VARIANT_AHLP (VARIANT_AH | VARIANT_LP)
|
||||
#define VARIANT_AHI (VARIANT_AH | VARIANT_INTEGER)
|
||||
#define VARIANT_AHK (VARIANT_AH | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHKLP (VARIANT_AHLP | VARIANT_KEYWORD)
|
||||
#define VARIANT_AUK (VARIANT_AUTO | VARIANT_URL | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHUK (VARIANT_AH | VARIANT_URL | VARIANT_KEYWORD)
|
||||
#define VARIANT_AHL (VARIANT_AH | VARIANT_LENGTH)
|
||||
#define VARIANT_AHKL (VARIANT_AHK | VARIANT_LENGTH)
|
||||
#define VARIANT_HK (VARIANT_INHERIT | VARIANT_KEYWORD)
|
||||
#define VARIANT_HKF (VARIANT_HK | VARIANT_FREQUENCY)
|
||||
#define VARIANT_HKL (VARIANT_HK | VARIANT_LENGTH)
|
||||
#define VARIANT_HKLP (VARIANT_HK | VARIANT_LP)
|
||||
#define VARIANT_HKLPO (VARIANT_HKLP | VARIANT_NONE)
|
||||
#define VARIANT_HL (VARIANT_INHERIT | VARIANT_LENGTH)
|
||||
#define VARIANT_HI (VARIANT_INHERIT | VARIANT_INTEGER)
|
||||
#define VARIANT_HLP (VARIANT_HL | VARIANT_PERCENT)
|
||||
#define VARIANT_HLPN (VARIANT_HLP | VARIANT_NUMBER)
|
||||
#define VARIANT_HLPO (VARIANT_HLP | VARIANT_NONE)
|
||||
#define VARIANT_HTP (VARIANT_INHERIT | VARIANT_TIME | VARIANT_PERCENT)
|
||||
#define VARIANT_HMK (VARIANT_HK | VARIANT_NORMAL)
|
||||
#define VARIANT_HMKI (VARIANT_HMK | VARIANT_INTEGER)
|
||||
#define VARIANT_HC (VARIANT_INHERIT | VARIANT_COLOR)
|
||||
#define VARIANT_HCK (VARIANT_HK | VARIANT_COLOR)
|
||||
#define VARIANT_HUO (VARIANT_INHERIT | VARIANT_URL | VARIANT_NONE)
|
||||
#define VARIANT_AHUO (VARIANT_AUTO | VARIANT_HUO)
|
||||
#define VARIANT_HPN (VARIANT_INHERIT | VARIANT_PERCENT | VARIANT_NUMBER)
|
||||
#define VARIANT_HOK (VARIANT_HK | VARIANT_NONE)
|
||||
#define VARIANT_HN (VARIANT_INHERIT | VARIANT_NUMBER)
|
||||
#define VARIANT_HON (VARIANT_HN | VARIANT_NONE)
|
||||
#define VARIANT_HOS (VARIANT_INHERIT | VARIANT_NONE | VARIANT_STRING)
|
||||
|
||||
static const nsCSSProperty kBorderTopIDs[] = {
|
||||
eCSSProperty_border_top_width,
|
||||
eCSSProperty_border_top_style,
|
||||
|
@ -75,6 +75,8 @@
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsCSSDeclaration.h"
|
||||
#include "nsRuleNode.h"
|
||||
|
||||
// -------------------------------
|
||||
// Style Rule List for the DOM
|
||||
@ -163,6 +165,264 @@ CSSRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Numeric>
|
||||
PRInt32 DoCompare(Numeric a, Numeric b)
|
||||
{
|
||||
if (a == b)
|
||||
return 0;
|
||||
if (a < b)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMediaExpression::Matches(nsPresContext *aPresContext,
|
||||
const nsCSSValue& aActualValue) const
|
||||
{
|
||||
const nsCSSValue& actual = aActualValue;
|
||||
const nsCSSValue& required = mValue;
|
||||
|
||||
// If we don't have the feature, the match fails.
|
||||
if (actual.GetUnit() == eCSSUnit_Null) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// If the expression had no value to match, the match succeeds,
|
||||
// unless the value is an integer 0.
|
||||
if (required.GetUnit() == eCSSUnit_Null) {
|
||||
return actual.GetUnit() != eCSSUnit_Integer ||
|
||||
actual.GetIntValue() != 0;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mFeature->mRangeType == nsMediaFeature::eMinMaxAllowed ||
|
||||
mRange == nsMediaExpression::eEqual, "yikes");
|
||||
PRInt32 cmp; // -1 (actual < required)
|
||||
// 0 (actual == required)
|
||||
// 1 (actual > required)
|
||||
switch (mFeature->mValueType) {
|
||||
case nsMediaFeature::eLength:
|
||||
{
|
||||
NS_ASSERTION(actual.IsLengthUnit(), "bad actual value");
|
||||
NS_ASSERTION(required.IsLengthUnit(), "bad required value");
|
||||
nscoord actualCoord = nsRuleNode::CalcLengthWithInitialFont(
|
||||
aPresContext, actual);
|
||||
nscoord requiredCoord = nsRuleNode::CalcLengthWithInitialFont(
|
||||
aPresContext, required);
|
||||
cmp = DoCompare(actualCoord, requiredCoord);
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eInteger:
|
||||
{
|
||||
NS_ASSERTION(actual.GetUnit() == eCSSUnit_Integer,
|
||||
"bad actual value");
|
||||
NS_ASSERTION(required.GetUnit() == eCSSUnit_Integer,
|
||||
"bad required value");
|
||||
cmp = DoCompare(actual.GetIntValue(), required.GetIntValue());
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eIntRatio:
|
||||
{
|
||||
NS_ASSERTION(actual.GetUnit() == eCSSUnit_Array &&
|
||||
actual.GetArrayValue()->Count() == 2 &&
|
||||
actual.GetArrayValue()->Item(0).GetUnit() ==
|
||||
eCSSUnit_Integer &&
|
||||
actual.GetArrayValue()->Item(1).GetUnit() ==
|
||||
eCSSUnit_Integer,
|
||||
"bad actual value");
|
||||
NS_ASSERTION(required.GetUnit() == eCSSUnit_Array &&
|
||||
required.GetArrayValue()->Count() == 2 &&
|
||||
required.GetArrayValue()->Item(0).GetUnit() ==
|
||||
eCSSUnit_Integer &&
|
||||
required.GetArrayValue()->Item(1).GetUnit() ==
|
||||
eCSSUnit_Integer,
|
||||
"bad required value");
|
||||
// Convert to PRInt64 so we can multiply without worry. Note
|
||||
// that while the spec requires that both halves of |required|
|
||||
// be positive, the numerator or denominator of |actual| might
|
||||
// be zero (e.g., when testing 'aspect-ratio' on a 0-width or
|
||||
// 0-height iframe).
|
||||
PRInt64 actualNum = actual.GetArrayValue()->Item(0).GetIntValue(),
|
||||
actualDen = actual.GetArrayValue()->Item(1).GetIntValue(),
|
||||
requiredNum = required.GetArrayValue()->Item(0).GetIntValue(),
|
||||
requiredDen = required.GetArrayValue()->Item(1).GetIntValue();
|
||||
cmp = DoCompare(actualNum * requiredDen, requiredNum * actualDen);
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eResolution:
|
||||
{
|
||||
NS_ASSERTION(actual.GetUnit() == eCSSUnit_Inch ||
|
||||
actual.GetUnit() == eCSSUnit_Centimeter,
|
||||
"bad actual value");
|
||||
NS_ASSERTION(required.GetUnit() == eCSSUnit_Inch ||
|
||||
required.GetUnit() == eCSSUnit_Centimeter,
|
||||
"bad required value");
|
||||
float actualDPI = actual.GetFloatValue();
|
||||
if (actual.GetUnit() == eCSSUnit_Centimeter)
|
||||
actualDPI = actualDPI * 2.54f;
|
||||
float requiredDPI = required.GetFloatValue();
|
||||
if (required.GetUnit() == eCSSUnit_Centimeter)
|
||||
requiredDPI = requiredDPI * 2.54f;
|
||||
cmp = DoCompare(actualDPI, requiredDPI);
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eEnumerated:
|
||||
{
|
||||
NS_ASSERTION(actual.GetUnit() == eCSSUnit_Enumerated,
|
||||
"bad actual value");
|
||||
NS_ASSERTION(required.GetUnit() == eCSSUnit_Enumerated,
|
||||
"bad required value");
|
||||
NS_ASSERTION(mFeature->mRangeType == nsMediaFeature::eMinMaxNotAllowed,
|
||||
"bad range"); // we asserted above about mRange
|
||||
// We don't really need DoCompare, but it doesn't hurt (and
|
||||
// maybe the compiler will condense this case with eInteger).
|
||||
cmp = DoCompare(actual.GetIntValue(), required.GetIntValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (mRange) {
|
||||
case nsMediaExpression::eMin:
|
||||
return cmp != -1;
|
||||
case nsMediaExpression::eMax:
|
||||
return cmp != 1;
|
||||
case nsMediaExpression::eEqual:
|
||||
return cmp == 0;
|
||||
}
|
||||
NS_NOTREACHED("unexpected mRange");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsMediaQuery::AppendToString(nsAString& aString) const
|
||||
{
|
||||
nsAutoString buffer;
|
||||
|
||||
if (mHadUnknownExpression) {
|
||||
aString.AppendLiteral("not all");
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mNegated || !mHasOnly, "can't have not and only");
|
||||
NS_ASSERTION(!mTypeOmitted || (!mNegated && !mHasOnly),
|
||||
"can't have not or only when type is omitted");
|
||||
if (!mTypeOmitted) {
|
||||
if (mNegated) {
|
||||
aString.AppendLiteral("not ");
|
||||
} else if (mHasOnly) {
|
||||
aString.AppendLiteral("only ");
|
||||
}
|
||||
mMediaType->ToString(buffer);
|
||||
aString.Append(buffer);
|
||||
buffer.Truncate();
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0, i_end = mExpressions.Length(); i < i_end; ++i) {
|
||||
if (i > 0 || !mTypeOmitted)
|
||||
aString.AppendLiteral(" and ");
|
||||
aString.AppendLiteral("(");
|
||||
|
||||
const nsMediaExpression &expr = mExpressions[i];
|
||||
if (expr.mRange == nsMediaExpression::eMin) {
|
||||
aString.AppendLiteral("min-");
|
||||
} else if (expr.mRange == nsMediaExpression::eMax) {
|
||||
aString.AppendLiteral("max-");
|
||||
}
|
||||
|
||||
const nsMediaFeature *feature = expr.mFeature;
|
||||
(*feature->mName)->ToString(buffer);
|
||||
aString.Append(buffer);
|
||||
buffer.Truncate();
|
||||
|
||||
if (expr.mValue.GetUnit() != eCSSUnit_Null) {
|
||||
aString.AppendLiteral(": ");
|
||||
switch (feature->mValueType) {
|
||||
case nsMediaFeature::eLength:
|
||||
NS_ASSERTION(expr.mValue.IsLengthUnit(), "bad unit");
|
||||
// Use 'width' as a property that takes length values
|
||||
// written in the normal way.
|
||||
nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_width,
|
||||
expr.mValue, aString);
|
||||
break;
|
||||
case nsMediaFeature::eInteger:
|
||||
NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Integer,
|
||||
"bad unit");
|
||||
// Use 'z-index' as a property that takes integer values
|
||||
// written without anything extra.
|
||||
nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_z_index,
|
||||
expr.mValue, aString);
|
||||
break;
|
||||
case nsMediaFeature::eIntRatio:
|
||||
{
|
||||
NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Array,
|
||||
"bad unit");
|
||||
nsCSSValue::Array *array = expr.mValue.GetArrayValue();
|
||||
NS_ASSERTION(array->Count() == 2, "unexpected length");
|
||||
NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
|
||||
"bad unit");
|
||||
NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Integer,
|
||||
"bad unit");
|
||||
nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_z_index,
|
||||
array->Item(0), aString);
|
||||
aString.AppendLiteral("/");
|
||||
nsCSSDeclaration::AppendCSSValueToString(eCSSProperty_z_index,
|
||||
array->Item(1), aString);
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eResolution:
|
||||
buffer.AppendFloat(expr.mValue.GetFloatValue());
|
||||
aString.Append(buffer);
|
||||
buffer.Truncate();
|
||||
if (expr.mValue.GetUnit() == eCSSUnit_Inch) {
|
||||
aString.AppendLiteral("dpi");
|
||||
} else {
|
||||
NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Centimeter,
|
||||
"bad unit");
|
||||
aString.AppendLiteral("dpcm");
|
||||
}
|
||||
break;
|
||||
case nsMediaFeature::eEnumerated:
|
||||
NS_ASSERTION(expr.mValue.GetUnit() == eCSSUnit_Enumerated,
|
||||
"bad unit");
|
||||
AppendASCIItoUTF16(
|
||||
nsCSSProps::ValueToKeyword(expr.mValue.GetIntValue(),
|
||||
feature->mKeywordTable),
|
||||
aString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
aString.AppendLiteral(")");
|
||||
}
|
||||
}
|
||||
|
||||
nsMediaQuery*
|
||||
nsMediaQuery::Clone() const
|
||||
{
|
||||
nsAutoPtr<nsMediaQuery> result(new nsMediaQuery(*this));
|
||||
NS_ENSURE_TRUE(result &&
|
||||
result->mExpressions.Length() == mExpressions.Length(),
|
||||
nsnull);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMediaQuery::Matches(nsPresContext* aPresContext) const
|
||||
{
|
||||
if (mHadUnknownExpression)
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool match =
|
||||
mMediaType == aPresContext->Medium() || mMediaType == nsGkAtoms::all;
|
||||
for (PRUint32 i = 0, i_end = mExpressions.Length(); match && i < i_end; ++i) {
|
||||
const nsMediaExpression &expr = mExpressions[i];
|
||||
nsCSSValue actual;
|
||||
nsresult rv = (expr.mFeature->mGetter)(aPresContext, actual);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE); // any better ideas?
|
||||
match = expr.Matches(aPresContext, actual);
|
||||
}
|
||||
|
||||
return match == !mNegated;
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsMediaList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMMediaList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
@ -174,7 +434,8 @@ NS_IMPL_RELEASE(nsMediaList)
|
||||
|
||||
|
||||
nsMediaList::nsMediaList()
|
||||
: mStyleSheet(nsnull)
|
||||
: mIsEmpty(PR_TRUE)
|
||||
, mStyleSheet(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
@ -187,13 +448,16 @@ nsMediaList::GetText(nsAString& aMediaText)
|
||||
{
|
||||
aMediaText.Truncate();
|
||||
|
||||
for (PRInt32 i = 0, i_end = mArray.Count(); i < i_end; ++i) {
|
||||
nsIAtom* medium = mArray[i];
|
||||
NS_ENSURE_TRUE(medium, NS_ERROR_FAILURE);
|
||||
if (mArray.Length() == 0 && !mIsEmpty) {
|
||||
aMediaText.AppendLiteral("not all");
|
||||
}
|
||||
|
||||
for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
|
||||
nsMediaQuery* query = mArray[i];
|
||||
NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
|
||||
|
||||
query->AppendToString(aMediaText);
|
||||
|
||||
nsAutoString buffer;
|
||||
medium->ToString(buffer);
|
||||
aMediaText.Append(buffer);
|
||||
if (i + 1 < i_end) {
|
||||
aMediaText.AppendLiteral(", ");
|
||||
}
|
||||
@ -224,18 +488,15 @@ nsMediaList::SetText(const nsAString& aMediaText)
|
||||
this, htmlMode);
|
||||
}
|
||||
|
||||
/*
|
||||
* aMatch is true when we contain the desired medium or contain the
|
||||
* "all" medium or contain no media at all, which is the same as
|
||||
* containing "all"
|
||||
*/
|
||||
PRBool
|
||||
nsMediaList::Matches(nsPresContext* aPresContext)
|
||||
{
|
||||
if (-1 != mArray.IndexOf(aPresContext->Medium()) ||
|
||||
-1 != mArray.IndexOf(nsGkAtoms::all))
|
||||
return PR_TRUE;
|
||||
return mArray.Count() == 0;
|
||||
for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
|
||||
if (mArray[i]->Matches(aPresContext)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return mIsEmpty;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -251,10 +512,13 @@ nsresult
|
||||
nsMediaList::Clone(nsMediaList** aResult)
|
||||
{
|
||||
nsRefPtr<nsMediaList> result = new nsMediaList();
|
||||
if (!result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!result->mArray.AppendObjects(mArray))
|
||||
if (!result || !result->mArray.AppendElements(mArray.Length()))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
|
||||
if (!(result->mArray[i] = mArray[i]->Clone())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
NS_ADDREF(*aResult = result);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -310,7 +574,7 @@ nsMediaList::GetLength(PRUint32* aLength)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLength);
|
||||
|
||||
*aLength = mArray.Count();
|
||||
*aLength = mArray.Length();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -319,7 +583,11 @@ nsMediaList::Item(PRUint32 aIndex, nsAString& aReturn)
|
||||
{
|
||||
PRInt32 index = aIndex;
|
||||
if (0 <= index && index < Count()) {
|
||||
MediumAt(aIndex)->ToString(aReturn);
|
||||
nsMediaQuery* query = mArray[index];
|
||||
NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
|
||||
|
||||
aReturn.Truncate();
|
||||
query->AppendToString(aReturn);
|
||||
} else {
|
||||
SetDOMStringToNull(aReturn);
|
||||
}
|
||||
@ -367,18 +635,19 @@ nsMediaList::Delete(const nsAString& aOldMedium)
|
||||
if (aOldMedium.IsEmpty())
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
|
||||
nsCOMPtr<nsIAtom> old = do_GetAtom(aOldMedium);
|
||||
NS_ENSURE_TRUE(old, NS_ERROR_OUT_OF_MEMORY);
|
||||
for (PRInt32 i = 0, i_end = mArray.Length(); i < i_end; ++i) {
|
||||
nsMediaQuery* query = mArray[i];
|
||||
NS_ENSURE_TRUE(query, NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 indx = mArray.IndexOf(old);
|
||||
|
||||
if (indx < 0) {
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
nsAutoString buf;
|
||||
query->AppendToString(buf);
|
||||
if (buf == aOldMedium) {
|
||||
mArray.RemoveElementAt(i);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
mArray.RemoveObjectAt(indx);
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -387,18 +656,31 @@ nsMediaList::Append(const nsAString& aNewMedium)
|
||||
if (aNewMedium.IsEmpty())
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
|
||||
nsCOMPtr<nsIAtom> media = do_GetAtom(aNewMedium);
|
||||
NS_ENSURE_TRUE(media, NS_ERROR_OUT_OF_MEMORY);
|
||||
Delete(aNewMedium);
|
||||
|
||||
PRInt32 indx = mArray.IndexOf(media);
|
||||
|
||||
if (indx >= 0) {
|
||||
mArray.RemoveObjectAt(indx);
|
||||
nsresult rv = NS_OK;
|
||||
nsTArray<nsAutoPtr<nsMediaQuery> > buf;
|
||||
#ifdef DEBUG
|
||||
PRBool ok =
|
||||
#endif
|
||||
mArray.SwapElements(buf);
|
||||
NS_ASSERTION(ok, "SwapElements should never fail when neither array "
|
||||
"is an auto array");
|
||||
SetText(aNewMedium);
|
||||
if (mArray.Length() == 1) {
|
||||
nsMediaQuery *query = mArray[0].forget();
|
||||
if (!buf.AppendElement(query)) {
|
||||
delete query;
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
mArray.AppendObject(media);
|
||||
|
||||
return NS_OK;
|
||||
#ifdef DEBUG
|
||||
ok =
|
||||
#endif
|
||||
mArray.SwapElements(buf);
|
||||
NS_ASSERTION(ok, "SwapElements should never fail when neither array "
|
||||
"is an auto array");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
|
@ -21,6 +21,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -46,12 +47,84 @@
|
||||
|
||||
#include "nsIDOMMediaList.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsMediaFeatures.h"
|
||||
#include "nsCSSValue.h"
|
||||
|
||||
class nsPresContext;
|
||||
class nsICSSStyleSheet;
|
||||
class nsCSSStyleSheet;
|
||||
|
||||
struct nsMediaExpression {
|
||||
enum Range { eMin, eMax, eEqual };
|
||||
|
||||
const nsMediaFeature *mFeature;
|
||||
Range mRange;
|
||||
nsCSSValue mValue;
|
||||
|
||||
// aActualValue must be obtained from mFeature->mGetter
|
||||
PRBool Matches(nsPresContext* aPresContext,
|
||||
const nsCSSValue& aActualValue) const;
|
||||
};
|
||||
|
||||
class nsMediaQuery {
|
||||
public:
|
||||
nsMediaQuery()
|
||||
: mNegated(PR_FALSE)
|
||||
, mHasOnly(PR_FALSE)
|
||||
, mTypeOmitted(PR_FALSE)
|
||||
, mHadUnknownExpression(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
// for Clone only
|
||||
nsMediaQuery(const nsMediaQuery& aOther)
|
||||
: mNegated(aOther.mNegated)
|
||||
, mHasOnly(aOther.mHasOnly)
|
||||
, mTypeOmitted(aOther.mTypeOmitted)
|
||||
, mHadUnknownExpression(aOther.mHadUnknownExpression)
|
||||
, mMediaType(aOther.mMediaType)
|
||||
// Clone checks the result of this deep copy for allocation failure
|
||||
, mExpressions(aOther.mExpressions)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void SetNegated() { mNegated = PR_TRUE; }
|
||||
void SetHasOnly() { mHasOnly = PR_TRUE; }
|
||||
void SetTypeOmitted() { mTypeOmitted = PR_TRUE; }
|
||||
void SetHadUnknownExpression() { mHadUnknownExpression = PR_TRUE; }
|
||||
void SetType(nsIAtom* aMediaType) {
|
||||
NS_ASSERTION(aMediaType,
|
||||
"expected non-null");
|
||||
mMediaType = aMediaType;
|
||||
}
|
||||
|
||||
// Return a new nsMediaExpression in the array for the caller to fill
|
||||
// in. The caller must either fill it in completely, or call
|
||||
// SetHadUnknownExpression on this nsMediaQuery.
|
||||
// Returns null on out-of-memory.
|
||||
nsMediaExpression* NewExpression() { return mExpressions.AppendElement(); }
|
||||
|
||||
void AppendToString(nsAString& aString) const;
|
||||
|
||||
nsMediaQuery* Clone() const;
|
||||
|
||||
// Does this query apply to the presentation?
|
||||
PRBool Matches(nsPresContext* aPresContext) const;
|
||||
|
||||
private:
|
||||
PRPackedBool mNegated;
|
||||
PRPackedBool mHasOnly; // only needed for serialization
|
||||
PRPackedBool mTypeOmitted; // only needed for serialization
|
||||
PRPackedBool mHadUnknownExpression;
|
||||
nsCOMPtr<nsIAtom> mMediaType;
|
||||
nsTArray<nsMediaExpression> mExpressions;
|
||||
};
|
||||
|
||||
class nsMediaList : public nsIDOMMediaList {
|
||||
public:
|
||||
nsMediaList();
|
||||
@ -64,15 +137,24 @@ public:
|
||||
nsresult SetText(const nsAString& aMediaText);
|
||||
PRBool Matches(nsPresContext* aPresContext);
|
||||
nsresult SetStyleSheet(nsICSSStyleSheet* aSheet);
|
||||
nsresult AppendAtom(nsIAtom* aMediumAtom) {
|
||||
return mArray.AppendObject(aMediumAtom) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
nsresult AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) {
|
||||
// Takes ownership of aQuery (if it succeeds)
|
||||
if (!mArray.AppendElement(aQuery.get())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
aQuery.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Clone(nsMediaList** aResult);
|
||||
|
||||
PRInt32 Count() { return mArray.Count(); }
|
||||
nsIAtom* MediumAt(PRInt32 aIndex) { return mArray[aIndex]; }
|
||||
void Clear() { mArray.Clear(); }
|
||||
PRInt32 Count() { return mArray.Length(); }
|
||||
nsMediaQuery* MediumAt(PRInt32 aIndex) { return mArray[aIndex]; }
|
||||
void Clear() { mArray.Clear(); mIsEmpty = PR_TRUE; }
|
||||
// a media list with no items may not represent the lack of a media
|
||||
// list; it could represent the empty string or something with parser
|
||||
// errors, which means that the media list should never match
|
||||
void SetNonEmpty() { mIsEmpty = PR_FALSE; }
|
||||
|
||||
protected:
|
||||
~nsMediaList();
|
||||
@ -80,7 +162,8 @@ protected:
|
||||
nsresult Delete(const nsAString & aOldMedium);
|
||||
nsresult Append(const nsAString & aOldMedium);
|
||||
|
||||
nsCOMArray<nsIAtom> mArray;
|
||||
nsTArray<nsAutoPtr<nsMediaQuery> > mArray;
|
||||
PRBool mIsEmpty;
|
||||
// not refcounted; sheet will let us know when it goes away
|
||||
// mStyleSheet is the sheet that needs to be dirtied when this medialist
|
||||
// changes
|
||||
|
328
layout/style/nsMediaFeatures.cpp
Normal file
328
layout/style/nsMediaFeatures.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsMediaFeatures.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* the features that media queries can test */
|
||||
|
||||
#include "nsMediaFeatures.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsCSSKeywords.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsCSSValue.h"
|
||||
|
||||
static const PRInt32 kOrientationKeywords[] = {
|
||||
eCSSKeyword_portrait, NS_STYLE_ORIENTATION_PORTRAIT,
|
||||
eCSSKeyword_landscape, NS_STYLE_ORIENTATION_LANDSCAPE,
|
||||
eCSSKeyword_UNKNOWN, -1
|
||||
};
|
||||
|
||||
static const PRInt32 kScanKeywords[] = {
|
||||
eCSSKeyword_progressive, NS_STYLE_SCAN_PROGRESSIVE,
|
||||
eCSSKeyword_interlace, NS_STYLE_SCAN_INTERLACE,
|
||||
eCSSKeyword_UNKNOWN, -1
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetWidth(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
nscoord width = aPresContext->GetVisibleArea().width;
|
||||
float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(width);
|
||||
aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetHeight(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
nscoord height = aPresContext->GetVisibleArea().height;
|
||||
float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(height);
|
||||
aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetDeviceWidth(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// XXX: I'm not sure if this is really the right thing for print:
|
||||
// do we want to include unprintable areas / page margins?
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
nscoord width, height;
|
||||
dx->GetDeviceSurfaceDimensions(width, height);
|
||||
float pixelWidth = aPresContext->AppUnitsToFloatCSSPixels(width);
|
||||
aResult.SetFloatValue(pixelWidth, eCSSUnit_Pixel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetDeviceHeight(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// XXX: I'm not sure if this is really the right thing for print:
|
||||
// do we want to include unprintable areas / page margins?
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
nscoord width, height;
|
||||
dx->GetDeviceSurfaceDimensions(width, height);
|
||||
float pixelHeight = aPresContext->AppUnitsToFloatCSSPixels(height);
|
||||
aResult.SetFloatValue(pixelHeight, eCSSUnit_Pixel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetOrientation(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
nsSize size = aPresContext->GetVisibleArea().Size();
|
||||
PRInt32 orientation;
|
||||
if (size.width > size.height) {
|
||||
orientation = NS_STYLE_ORIENTATION_LANDSCAPE;
|
||||
} else {
|
||||
// Per spec, square viewports should be 'portrait'
|
||||
orientation = NS_STYLE_ORIENTATION_PORTRAIT;
|
||||
}
|
||||
|
||||
aResult.SetIntValue(orientation, eCSSUnit_Enumerated);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetAspectRatio(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
nsRefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
|
||||
NS_ENSURE_TRUE(a, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsSize size = aPresContext->GetVisibleArea().Size();
|
||||
a->Item(0).SetIntValue(size.width, eCSSUnit_Integer);
|
||||
a->Item(1).SetIntValue(size.height, eCSSUnit_Integer);
|
||||
|
||||
aResult.SetArrayValue(a, eCSSUnit_Array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetDeviceAspectRatio(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
nsRefPtr<nsCSSValue::Array> a = nsCSSValue::Array::Create(2);
|
||||
NS_ENSURE_TRUE(a, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// XXX: I'm not sure if this is really the right thing for print:
|
||||
// do we want to include unprintable areas / page margins?
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
nscoord width, height;
|
||||
dx->GetDeviceSurfaceDimensions(width, height);
|
||||
a->Item(0).SetIntValue(width, eCSSUnit_Integer);
|
||||
a->Item(1).SetIntValue(height, eCSSUnit_Integer);
|
||||
|
||||
aResult.SetArrayValue(a, eCSSUnit_Array);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetColor(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// FIXME: This implementation is bogus. nsThebesDeviceContext
|
||||
// doesn't provide reliable information (should be fixed in bug
|
||||
// 424386).
|
||||
// FIXME: On a monochrome device, return 0!
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
PRUint32 depth;
|
||||
dx->GetDepth(depth);
|
||||
// Some graphics backends may claim 32-bit depth when it's really 24
|
||||
// (because they're counting the Alpha component).
|
||||
if (depth == 32) {
|
||||
depth = 24;
|
||||
}
|
||||
// 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(PRInt32(depth), eCSSUnit_Integer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetColorIndex(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// We should return zero if the device does not use a color lookup
|
||||
// table. Stuart says that our handling of displays with 8-bit
|
||||
// color is bad enough that we never change the lookup table to
|
||||
// match what we're trying to display, so perhaps we should always
|
||||
// return zero. Given that there isn't any better information
|
||||
// exposed, we don't have much other choice.
|
||||
aResult.SetIntValue(0, eCSSUnit_Integer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetMonochrome(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// For color devices we should return 0.
|
||||
// FIXME: On a monochrome device, return the actual color depth, not
|
||||
// 0!
|
||||
aResult.SetIntValue(0, eCSSUnit_Integer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetResolution(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// Resolution values are in device pixels, not CSS pixels.
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
float dpi = float(dx->AppUnitsPerInch()) / float(dx->AppUnitsPerDevPixel());
|
||||
aResult.SetFloatValue(dpi, eCSSUnit_Inch);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetScan(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// Since Gecko doesn't support the 'tv' media type, the 'scan'
|
||||
// feature is never present.
|
||||
aResult.Reset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
GetGrid(nsPresContext* aPresContext, nsCSSValue& aResult)
|
||||
{
|
||||
// Gecko doesn't support grid devices (e.g., ttys), so the 'grid'
|
||||
// feature is always 0.
|
||||
aResult.SetIntValue(0, eCSSUnit_Integer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ const nsMediaFeature
|
||||
nsMediaFeatures::features[] = {
|
||||
{
|
||||
&nsGkAtoms::width,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eLength,
|
||||
nsnull,
|
||||
GetWidth
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::height,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eLength,
|
||||
nsnull,
|
||||
GetHeight
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::deviceWidth,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eLength,
|
||||
nsnull,
|
||||
GetDeviceWidth
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::deviceHeight,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eLength,
|
||||
nsnull,
|
||||
GetDeviceHeight
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::orientation,
|
||||
nsMediaFeature::eMinMaxNotAllowed,
|
||||
nsMediaFeature::eEnumerated,
|
||||
kOrientationKeywords,
|
||||
GetOrientation
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::aspectRatio,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eIntRatio,
|
||||
nsnull,
|
||||
GetAspectRatio
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::deviceAspectRatio,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eIntRatio,
|
||||
nsnull,
|
||||
GetDeviceAspectRatio
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::color,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eInteger,
|
||||
nsnull,
|
||||
GetColor
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::colorIndex,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eInteger,
|
||||
nsnull,
|
||||
GetColorIndex
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::monochrome,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eInteger,
|
||||
nsnull,
|
||||
GetMonochrome
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::resolution,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eResolution,
|
||||
nsnull,
|
||||
GetResolution
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::scan,
|
||||
nsMediaFeature::eMinMaxNotAllowed,
|
||||
nsMediaFeature::eEnumerated,
|
||||
kScanKeywords,
|
||||
GetScan
|
||||
},
|
||||
{
|
||||
&nsGkAtoms::grid,
|
||||
nsMediaFeature::eMinMaxNotAllowed,
|
||||
nsMediaFeature::eInteger,
|
||||
nsnull,
|
||||
GetGrid
|
||||
},
|
||||
// Null-mName terminator:
|
||||
{
|
||||
nsnull,
|
||||
nsMediaFeature::eMinMaxAllowed,
|
||||
nsMediaFeature::eInteger,
|
||||
nsnull,
|
||||
nsnull
|
||||
},
|
||||
};
|
91
layout/style/nsMediaFeatures.h
Normal file
91
layout/style/nsMediaFeatures.h
Normal file
@ -0,0 +1,91 @@
|
||||
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsMediaFeatures.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/* the features that media queries can test */
|
||||
|
||||
#ifndef nsMediaFeatures_h_
|
||||
#define nsMediaFeatures_h_
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsPresContext;
|
||||
class nsCSSValue;
|
||||
|
||||
typedef nsresult
|
||||
(* PR_CALLBACK nsMediaFeatureValueGetter)(nsPresContext* aPresContext,
|
||||
nsCSSValue& aResult);
|
||||
|
||||
struct nsMediaFeature {
|
||||
nsIAtom **mName; // extra indirection to point to nsGkAtoms members
|
||||
|
||||
enum RangeType { eMinMaxAllowed, eMinMaxNotAllowed };
|
||||
RangeType mRangeType;
|
||||
|
||||
enum ValueType {
|
||||
// All value types allow eCSSUnit_Null to indicate that no value
|
||||
// was given (in addition to the types listed below).
|
||||
eLength, // values are such that nsCSSValue::IsLengthUnit() is true
|
||||
eInteger, // values are eCSSUnit_Integer
|
||||
eIntRatio, // values are eCSSUnit_Array of two eCSSUnit_Integer
|
||||
eResolution, // values are in eCSSUnit_Inch (for dpi) or
|
||||
// eCSSUnit_Centimeter (for dpcm)
|
||||
eEnumerated // values are eCSSUnit_Enumerated (uses keyword table)
|
||||
|
||||
// Note that a number of pieces of code (both for parsing and
|
||||
// for matching of valueless expressions) assume that all numeric
|
||||
// value types cannot be negative. The parsing code also does
|
||||
// not allow zeros in eIntRatio types.
|
||||
};
|
||||
ValueType mValueType;
|
||||
|
||||
// The same format as the keyword tables in nsCSSProps.
|
||||
const PRInt32* mKeywordTable;
|
||||
|
||||
// A function that returns the current value for this feature for a
|
||||
// given presentation. If it returns eCSSUnit_Null, the feature is
|
||||
// not present.
|
||||
nsMediaFeatureValueGetter mGetter;
|
||||
};
|
||||
|
||||
class nsMediaFeatures {
|
||||
public:
|
||||
// Terminated with an entry whose mName is null.
|
||||
static const nsMediaFeature features[];
|
||||
};
|
||||
|
||||
#endif /* !defined(nsMediaFeatures_h_) */
|
@ -241,6 +241,16 @@ static nscoord CalcLength(const nsCSSValue& aValue,
|
||||
return CalcLengthWith(aValue, -1, nsnull, aStyleContext, aPresContext, aInherited);
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
|
||||
const nsCSSValue& aValue)
|
||||
{
|
||||
nsStyleFont defaultFont(aPresContext);
|
||||
PRBool inherited;
|
||||
return CalcLengthWith(aValue, -1, &defaultFont, nsnull, aPresContext,
|
||||
inherited);
|
||||
}
|
||||
|
||||
#define SETCOORD_NORMAL 0x01 // N
|
||||
#define SETCOORD_AUTO 0x02 // A
|
||||
#define SETCOORD_INHERIT 0x04 // H
|
||||
|
@ -738,6 +738,10 @@ public:
|
||||
|
||||
static PRBool
|
||||
HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, PRUint32 ruleTypeMask);
|
||||
|
||||
// Expose this so media queries can use it
|
||||
static nscoord CalcLengthWithInitialFont(nsPresContext* aPresContext,
|
||||
const nsCSSValue& aValue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user