1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * representation of media lists used when linking to style sheets or by
12 #ifndef nsIMediaList_h_
13 #define nsIMediaList_h_
15 #include "nsIDOMMediaList.h"
18 #include "nsCSSValue.h"
19 #include "nsWrapperCache.h"
20 #include "mozilla/Attributes.h"
21 #include "mozilla/ErrorResult.h"
25 struct nsMediaFeature
;
29 } // namespace mozilla
31 struct nsMediaExpression
{
32 enum Range
{ eMin
, eMax
, eEqual
};
34 const nsMediaFeature
*mFeature
;
38 // aActualValue must be obtained from mFeature->mGetter
39 bool Matches(nsPresContext
* aPresContext
,
40 const nsCSSValue
& aActualValue
) const;
42 bool operator==(const nsMediaExpression
& aOther
) const {
43 return mFeature
== aOther
.mFeature
&& // pointer equality fine (atom-like)
44 mRange
== aOther
.mRange
&&
45 mValue
== aOther
.mValue
;
47 bool operator!=(const nsMediaExpression
& aOther
) const {
48 return !(*this == aOther
);
53 * An nsMediaQueryResultCacheKey records what feature/value combinations
54 * a set of media query results are valid for. This allows the caller
55 * to quickly learn whether a prior result of media query evaluation is
56 * still valid (e.g., due to a window size change) without rerunning all
57 * of the evaluation and rebuilding the list of rules.
59 * This object may not be used after any media rules in any of the
60 * sheets it was given to have been modified. However, this is
61 * generally not a problem since ClearRuleCascades is called on the
62 * sheet whenever this happens, and these objects are stored inside the
63 * rule cascades. (FIXME: We're not actually doing this all the time.)
65 * The implementation could be further optimized in the future to store
66 * ranges (combinations of less-than, less-than-or-equal, greater-than,
67 * greater-than-or-equal, equal, not-equal, present, not-present) for
68 * each feature rather than simply storing the list of expressions.
69 * However, this requires combining any such ranges.
71 class nsMediaQueryResultCacheKey
{
73 explicit nsMediaQueryResultCacheKey(nsIAtom
* aMedium
)
78 * Record that aExpression was tested while building the cached set
79 * that this cache key is for, and that aExpressionMatches was whether
82 void AddExpression(const nsMediaExpression
* aExpression
,
83 bool aExpressionMatches
);
84 bool Matches(nsPresContext
* aPresContext
) const;
85 bool HasFeatureConditions() const {
86 return !mFeatureCache
.IsEmpty();
90 * An operator== that implements list equality, which isn't quite as
91 * good as set equality, but catches the trivial equality cases.
93 bool operator==(const nsMediaQueryResultCacheKey
& aOther
) const {
94 return mMedium
== aOther
.mMedium
&&
95 mFeatureCache
== aOther
.mFeatureCache
;
97 bool operator!=(const nsMediaQueryResultCacheKey
& aOther
) const {
98 return !(*this == aOther
);
101 struct ExpressionEntry
{
102 // FIXME: if we were better at maintaining invariants about clearing
103 // rule cascades when media lists change, this could be a |const
104 // nsMediaExpression*| instead.
105 nsMediaExpression mExpression
;
106 bool mExpressionMatches
;
108 bool operator==(const ExpressionEntry
& aOther
) const {
109 return mExpression
== aOther
.mExpression
&&
110 mExpressionMatches
== aOther
.mExpressionMatches
;
112 bool operator!=(const ExpressionEntry
& aOther
) const {
113 return !(*this == aOther
);
116 struct FeatureEntry
{
117 const nsMediaFeature
*mFeature
;
118 InfallibleTArray
<ExpressionEntry
> mExpressions
;
120 bool operator==(const FeatureEntry
& aOther
) const {
121 return mFeature
== aOther
.mFeature
&&
122 mExpressions
== aOther
.mExpressions
;
124 bool operator!=(const FeatureEntry
& aOther
) const {
125 return !(*this == aOther
);
128 nsCOMPtr
<nsIAtom
> mMedium
;
129 nsTArray
<FeatureEntry
> mFeatureCache
;
137 , mTypeOmitted(false)
138 , mHadUnknownExpression(false)
144 nsMediaQuery(const nsMediaQuery
& aOther
)
145 : mNegated(aOther
.mNegated
)
146 , mHasOnly(aOther
.mHasOnly
)
147 , mTypeOmitted(aOther
.mTypeOmitted
)
148 , mHadUnknownExpression(aOther
.mHadUnknownExpression
)
149 , mMediaType(aOther
.mMediaType
)
150 , mExpressions(aOther
.mExpressions
)
152 MOZ_ASSERT(mExpressions
.Length() == aOther
.mExpressions
.Length());
157 void SetNegated() { mNegated
= true; }
158 void SetHasOnly() { mHasOnly
= true; }
159 void SetTypeOmitted() { mTypeOmitted
= true; }
160 void SetHadUnknownExpression() { mHadUnknownExpression
= true; }
161 void SetType(nsIAtom
* aMediaType
) {
162 NS_ASSERTION(aMediaType
,
163 "expected non-null");
164 mMediaType
= aMediaType
;
167 // Return a new nsMediaExpression in the array for the caller to fill
168 // in. The caller must either fill it in completely, or call
169 // SetHadUnknownExpression on this nsMediaQuery.
170 // Returns null on out-of-memory.
171 nsMediaExpression
* NewExpression() { return mExpressions
.AppendElement(); }
173 void AppendToString(nsAString
& aString
) const;
175 nsMediaQuery
* Clone() const;
177 // Does this query apply to the presentation?
178 // If |aKey| is non-null, add cache information to it.
179 bool Matches(nsPresContext
* aPresContext
,
180 nsMediaQueryResultCacheKey
* aKey
) const;
184 bool mHasOnly
; // only needed for serialization
185 bool mTypeOmitted
; // only needed for serialization
186 bool mHadUnknownExpression
;
187 nsCOMPtr
<nsIAtom
> mMediaType
;
188 nsTArray
<nsMediaExpression
> mExpressions
;
191 class nsMediaList MOZ_FINAL
: public nsIDOMMediaList
192 , public nsWrapperCache
195 typedef mozilla::ErrorResult ErrorResult
;
200 WrapObject(JSContext
* aCx
) MOZ_OVERRIDE
;
201 nsISupports
* GetParentObject() const
206 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
207 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsMediaList
)
209 NS_DECL_NSIDOMMEDIALIST
211 void GetText(nsAString
& aMediaText
);
212 void SetText(const nsAString
& aMediaText
);
214 // Does this query apply to the presentation?
215 // If |aKey| is non-null, add cache information to it.
216 bool Matches(nsPresContext
* aPresContext
,
217 nsMediaQueryResultCacheKey
* aKey
);
219 void SetStyleSheet(mozilla::CSSStyleSheet
* aSheet
);
220 void AppendQuery(nsAutoPtr
<nsMediaQuery
>& aQuery
) {
221 // Takes ownership of aQuery
222 mArray
.AppendElement(aQuery
.forget());
225 already_AddRefed
<nsMediaList
> Clone();
227 nsMediaQuery
* MediumAt(int32_t aIndex
) { return mArray
[aIndex
]; }
228 void Clear() { mArray
.Clear(); }
231 // XPCOM GetMediaText and SetMediaText are fine.
232 uint32_t Length() { return mArray
.Length(); }
233 void IndexedGetter(uint32_t aIndex
, bool& aFound
, nsAString
& aReturn
);
234 // XPCOM Item is fine.
235 void DeleteMedium(const nsAString
& aMedium
, ErrorResult
& aRv
)
237 aRv
= DeleteMedium(aMedium
);
239 void AppendMedium(const nsAString
& aMedium
, ErrorResult
& aRv
)
241 aRv
= AppendMedium(aMedium
);
247 nsresult
Delete(const nsAString
& aOldMedium
);
248 nsresult
Append(const nsAString
& aOldMedium
);
250 InfallibleTArray
<nsAutoPtr
<nsMediaQuery
> > mArray
;
251 // not refcounted; sheet will let us know when it goes away
252 // mStyleSheet is the sheet that needs to be dirtied when this medialist
254 mozilla::CSSStyleSheet
* mStyleSheet
;
256 #endif /* !defined(nsIMediaList_h_) */